ipe-7.1.4/0000755000175000017500000000000012120621776012156 5ustar otfriedotfriedipe-7.1.4/news.txt0000644000175000017500000016315312120621776013704 0ustar otfriedotfried-------------------------------------------------------------------- Ipe 7.1.4 (2013-3-15) * Windows binaries provided again. * Migrated to using Lua 5.2 (feature #113). * Fixed bug in "ipescript update-master" with several figures (bug #85). * Ipe scripts (to be run with "ipescript
Ipelib
Here is a list of all class members with links to the classes they belong to:

- m -


ipe-7.1.4/build/doc/blank.png0000644000175000017500000000167712120621776015632 0ustar otfriedotfried‰PNG  IHDR D¤ŠÆsRGB®ÎégAMA± üa cHRMz&€„ú€èu0ê`:˜pœºQ<PLTE 3f™Ìÿ333f3™3Ì3ÿ3f3fff™fÌfÿf™3™f™™™Ì™ÿ™Ì3ÌfÌ™ÌÌÌÿÌÿ3ÿfÿ™ÿÌÿÿÿ333f3™3Ì3ÿ333333f33™33Ì33ÿ33f33f3ff3™f3Ìf3ÿf3™33™3f™3™™3Ì™3ÿ™3Ì33Ì3fÌ3™Ì3ÌÌ3ÿÌ3ÿ33ÿ3fÿ3™ÿ3Ìÿ3ÿÿ3f3fff™fÌfÿf3f33ff3f™3fÌ3fÿ3fff3fffff™ffÌffÿff™f3™ff™f™™fÌ™fÿ™fÌf3ÌffÌf™ÌfÌÌfÿÌfÿf3ÿffÿf™ÿfÌÿfÿÿf™3™f™™™Ì™ÿ™3™33™f3™™3™Ì3™ÿ3™f™3f™ff™™f™Ìf™ÿf™™™3™™f™™™™™Ì™™ÿ™™Ì™3Ì™fÌ™™Ì™ÌÌ™ÿÌ™ÿ™3ÿ™fÿ™™ÿ™Ìÿ™ÿÿ™Ì3ÌfÌ™ÌÌÌÿÌ3Ì33Ìf3Ì™3ÌÌ3Ìÿ3ÌfÌ3fÌffÌ™fÌÌfÌÿfÌ™Ì3™Ìf™Ì™™ÌÌ™Ìÿ™ÌÌÌ3ÌÌfÌÌ™ÌÌÌÌÌÿÌÌÿÌ3ÿÌfÿÌ™ÿÌÌÿÌÿÿÌÿ3ÿfÿ™ÿÌÿÿÿ3ÿ33ÿf3ÿ™3ÿÌ3ÿÿ3ÿfÿ3fÿffÿ™fÿÌfÿÿfÿ™ÿ3™ÿf™ÿ™™ÿÌ™ÿÿ™ÿÌÿ3ÌÿfÌÿ™ÌÿÌÌÿÿÌÿÿÿ3ÿÿfÿÿ™ÿÿÌÿÿÿÿÿâââãããäääåååæææçççèèèéééêêêëëëìììíííîîîïïïðððñññòòòóóóôôôõõõööö÷÷÷øøøùùùúúúûûûüüüýýýþþþÿÿÿCA× pHYsÄÄ•+IDAT8Oc¸I0Œ*‡Àh8@Âh8Œ¨p­d.ºxˆ1IEND®B`‚ipe-7.1.4/build/doc/classipe_1_1_all_attributes.html0000644000175000017500000005577212120621776022271 0ustar otfriedotfried Ipelib: ipe::AllAttributes Class Reference
Ipelib
Public Member Functions | Public Attributes | List of all members
ipe::AllAttributes Class Reference

#include <ipeattributes.h>

Public Member Functions

 AllAttributes ()

Public Attributes

TPathMode iPathMode
Attribute iStroke
Attribute iFill
Attribute iDashStyle
Attribute iPen
bool iFArrow
bool iRArrow
Attribute iFArrowShape
Attribute iRArrowShape
Attribute iFArrowSize
Attribute iRArrowSize
Attribute iSymbolSize
Attribute iTextSize
THorizontalAlignment iHorizontalAlignment
TVerticalAlignment iVerticalAlignment
Attribute iTextStyle
TPinned iPinned
bool iTransformableText
TTransformations iTransformations
TLineJoin iLineJoin
TLineCap iLineCap
TFillRule iFillRule
Attribute iOpacity
Attribute iTiling
Attribute iGradient
Attribute iMarkShape

Detailed Description

Collection of all object attributes.

Constructor & Destructor Documentation

AllAttributes::AllAttributes ( )

Constructor sets default values.

Member Data Documentation

TPathMode ipe::AllAttributes::iPathMode

Should we stroke and/or fill?

Attribute ipe::AllAttributes::iStroke

Stroke color.

Attribute ipe::AllAttributes::iFill

Fill color.

Attribute ipe::AllAttributes::iDashStyle

Dash style.

Attribute ipe::AllAttributes::iPen

Pen (that is, line width).

bool ipe::AllAttributes::iFArrow

Arrow forward?

bool ipe::AllAttributes::iRArrow

Reverse arrow?

Attribute ipe::AllAttributes::iFArrowShape

Shape of forward arrows.

Attribute ipe::AllAttributes::iRArrowShape

Shape of reverse arrows.

Attribute ipe::AllAttributes::iFArrowSize

Forward arrow size.

Attribute ipe::AllAttributes::iRArrowSize

Reverse arrow size.

Attribute ipe::AllAttributes::iSymbolSize

Symbol size.

Attribute ipe::AllAttributes::iTextSize

Text size. Horizontal alignment of label objects.

THorizontalAlignment ipe::AllAttributes::iHorizontalAlignment
TVerticalAlignment ipe::AllAttributes::iVerticalAlignment

Vertical alignment of label objects.

Attribute ipe::AllAttributes::iTextStyle

Text style.

TPinned ipe::AllAttributes::iPinned

Pinned status. Should newly created text be transformable?

bool ipe::AllAttributes::iTransformableText

If this is false, newly created text will only allow translations. Otherwise, the value of iTranslations is used (as for other objects).

TTransformations ipe::AllAttributes::iTransformations

Allowed transformations.

TLineJoin ipe::AllAttributes::iLineJoin

Line join style.

TLineCap ipe::AllAttributes::iLineCap

Line cap style.

TFillRule ipe::AllAttributes::iFillRule

Shape fill rule.

Attribute ipe::AllAttributes::iOpacity

Opacity.

Attribute ipe::AllAttributes::iTiling

Tiling pattern.

Attribute ipe::AllAttributes::iGradient

Gradient pattern.

Attribute ipe::AllAttributes::iMarkShape

Shape of Mark to create.


The documentation for this class was generated from the following files:

ipe-7.1.4/build/doc/functions_0x66.html0000644000175000017500000002337712120621776017517 0ustar otfriedotfried Ipelib: Class Members
Ipelib
Here is a list of all class members with links to the classes they belong to:

- f -


ipe-7.1.4/build/doc/classipe_1_1_pan_tool.html0000644000175000017500000002450212120621776021051 0ustar otfriedotfried Ipelib: ipe::PanTool Class Reference
Ipelib
Public Member Functions | List of all members
ipe::PanTool Class Reference

#include <ipetool.h>

Inherits ipe::Tool.

Public Member Functions

 PanTool (CanvasBase *canvas, const Page *page, int view)
virtual void draw (Painter &painter) const
virtual void mouseButton (int button, bool press)
virtual void mouseMove ()
- Public Member Functions inherited from ipe::Tool
virtual ~Tool ()
virtual bool key (int code, int modifiers, String text)

Additional Inherited Members

- Protected Member Functions inherited from ipe::Tool
 Tool (CanvasBase *canvas)
- Protected Attributes inherited from ipe::Tool
CanvasBaseiCanvas

Detailed Description

A tool for panning the canvas.

Constructor & Destructor Documentation

PanTool::PanTool ( CanvasBase canvas,
const Page page,
int  view 
)

Member Function Documentation

void PanTool::draw ( Painter painter) const
virtual

Implements ipe::Tool.

void PanTool::mouseButton ( int  button,
bool  press 
)
virtual

Called when a mouse button is pressed or released on the canvas.

button is 1, 2, or 3, with Shift/Ctrl/Alt/Meta modifiers added in (as defined in CanvasBase::TModifiers. press is true for button-down, and false for button-up.

Reimplemented from ipe::Tool.

void PanTool::mouseMove ( )
virtual

Called when the mouse is moved on the canvas.

Reimplemented from ipe::Tool.


The documentation for this class was generated from the following files:

ipe-7.1.4/build/doc/classipe_1_1_pdf_dict.html0000644000175000017500000004356312120621776021022 0ustar otfriedotfried Ipelib: ipe::PdfDict Class Reference
Ipelib
Classes | Public Member Functions | List of all members
ipe::PdfDict Class Reference

#include <ipepdfparser.h>

Inherits ipe::PdfObj.

Classes

struct  Item

Public Member Functions

 PdfDict ()
 ~PdfDict ()
virtual const PdfDictdict () const
virtual void write (Stream &stream) const
void setStream (const Buffer &stream)
void add (String key, const PdfObj *obj)
const PdfObjget (String key, const PdfFile *file) const
int count () const
String key (int index) const
Buffer stream () const
bool deflated () const
- Public Member Functions inherited from ipe::PdfObj
virtual ~PdfObj ()=0
virtual const PdfNullnull () const
virtual const PdfBoolboolean () const
virtual const PdfNumbernumber () const
virtual const PdfStringstring () const
virtual const PdfNamename () const
virtual const PdfRefref () const
virtual const PdfArrayarray () const
String repr () const

Detailed Description

The PDF dictionary and stream objects.

A dictionary may or may not have attached stream data.

Constructor & Destructor Documentation

ipe::PdfDict::PdfDict ( )
inlineexplicit
PdfDict::~PdfDict ( )

Member Function Documentation

const PdfDict * PdfDict::dict ( ) const
virtual

Return this object as PDF dictionary object.

Reimplemented from ipe::PdfObj.

void PdfDict::write ( Stream stream) const
virtual

Implements ipe::PdfObj.

void PdfDict::setStream ( const Buffer stream)

Add stream data to this dictionary.

void PdfDict::add ( String  key,
const PdfObj obj 
)

Add a (key, value) pair to the dictionary.

Dictionary takes ownership of obj.

const PdfObj * PdfDict::get ( String  key,
const PdfFile file 
) const

Look up key in dictionary.

Indirect objects (references) are looked up if file is not zero, and the object referred to is returned. Returns 0 if key is not in dictionary.

int ipe::PdfDict::count ( ) const
inline
String ipe::PdfDict::key ( int  index) const
inline
Buffer ipe::PdfDict::stream ( ) const
inline
bool PdfDict::deflated ( ) const

Is this stream compressed with flate compression?


The documentation for this class was generated from the following files:

ipe-7.1.4/build/doc/structipe_1_1_gradient_1_1_stop.html0000644000175000017500000000775312120621776022770 0ustar otfriedotfried Ipelib: ipe::Gradient::Stop Struct Reference
Ipelib
Public Attributes | List of all members
ipe::Gradient::Stop Struct Reference

#include <ipeattributes.h>

Public Attributes

double offset
Color color

Detailed Description

A color stop.

Member Data Documentation

double ipe::Gradient::Stop::offset

Offset between 0.0 and 1.0.

Color ipe::Gradient::Stop::color

The color at this offset.


The documentation for this struct was generated from the following file:

ipe-7.1.4/build/doc/classipe_1_1_thumbnail.html0000644000175000017500000001436712120621776021231 0ustar otfriedotfried Ipelib: ipe::Thumbnail Class Reference
Ipelib
Public Member Functions | List of all members
ipe::Thumbnail Class Reference

#include <ipethumbs.h>

Public Member Functions

 Thumbnail (const Document *doc, int width)
 ~Thumbnail ()
int height () const
Buffer render (const Page *page, int view)

Constructor & Destructor Documentation

Thumbnail::Thumbnail ( const Document doc,
int  width 
)
Thumbnail::~Thumbnail ( )

Member Function Documentation

int ipe::Thumbnail::height ( ) const
inline
Buffer Thumbnail::render ( const Page page,
int  view 
)

The documentation for this class was generated from the following files:

ipe-7.1.4/build/doc/classipe_1_1_tell_stream.html0000644000175000017500000002155012120621776021551 0ustar otfriedotfried Ipelib: ipe::TellStream Class Reference
Ipelib
Public Member Functions | List of all members
ipe::TellStream Class Reference

#include <ipebase.h>

Inherits ipe::Stream.

Inherited by ipe::FileStream, and ipe::StringStream.

Public Member Functions

virtual long tell () const =0
- Public Member Functions inherited from ipe::Stream
virtual ~Stream ()
virtual void putChar (char ch)=0
virtual void close ()
virtual void putString (String s)
virtual void putCString (const char *s)
virtual void putRaw (const char *data, int size)
Streamoperator<< (char ch)
Streamoperator<< (const String &s)
Streamoperator<< (const char *s)
Streamoperator<< (int i)
Streamoperator<< (double d)
void putHexByte (char b)
void putXmlString (String s)

Detailed Description

Adds position feedback to IpeStream.

Member Function Documentation

virtual long ipe::TellStream::tell ( ) const
pure virtual

Implemented in ipe::FileStream, and ipe::StringStream.


The documentation for this class was generated from the following file:

ipe-7.1.4/build/doc/classipe_1_1_rect.html0000644000175000017500000006162512120621776020202 0ustar otfriedotfried Ipelib: ipe::Rect Class Reference
Ipelib
Public Member Functions | Related Functions | List of all members
ipe::Rect Class Reference

#include <ipegeo.h>

Public Member Functions

 Rect ()
 Rect (const Vector &c)
 Rect (const Vector &c1, const Vector &c2)
void clear ()
int isEmpty () const
double left () const
double right () const
double bottom () const
double top () const
Vector topRight () const
Vector bottomLeft () const
Vector topLeft () const
Vector bottomRight () const
double width () const
double height () const
void addPoint (const Vector &rhs)
void addRect (const Rect &rhs)
void clipTo (const Rect &rhs)
bool contains (const Vector &rhs) const
bool contains (const Rect &rhs) const
bool certainClearance (const Vector &v, double bound) const
bool intersects (const Rect &rhs) const

Related Functions

(Note that these are not member functions.)

Streamoperator<< (Stream &stream, const Rect &rhs)

Detailed Description

Axis-parallel rectangle (which can be empty)

Constructor & Destructor Documentation

ipe::Rect::Rect ( )
inlineexplicit

Create empty rectangle.

ipe::Rect::Rect ( const Vector c)
inlineexplicit

Create rectangle containing just the point c.

Rect::Rect ( const Vector c1,
const Vector c2 
)
explicit

Create rectangle containing points c1 and c2.

Member Function Documentation

void ipe::Rect::clear ( )
inline

Make rectangle empty.

int ipe::Rect::isEmpty ( ) const
inline

True if rectangle is empty.

double ipe::Rect::left ( ) const
inline

Return left side.

double ipe::Rect::right ( ) const
inline

Return right side.

double ipe::Rect::bottom ( ) const
inline

Return bottom side.

double ipe::Rect::top ( ) const
inline

Return top side.

Vector ipe::Rect::topRight ( ) const
inline

Return top right corner.

Vector ipe::Rect::bottomLeft ( ) const
inline

Return bottom left corner.

Vector ipe::Rect::topLeft ( ) const
inline

Return top left corner.

Vector ipe::Rect::bottomRight ( ) const
inline

Return bottom right corner.

double ipe::Rect::width ( ) const
inline

Return width.

double ipe::Rect::height ( ) const
inline

Return height.

void Rect::addPoint ( const Vector rhs)

Enlarge rectangle to contain point.

void Rect::addRect ( const Rect rhs)

Enlarge rectangle to contain rhs rectangle.

Does nothing if rhs is empty.

void Rect::clipTo ( const Rect cbox)

Clip rectangle to fit inside cbox.

Does nothing if either rectangle is empty.

bool Rect::contains ( const Vector rhs) const

Does (closed) rectangle contain the point?

bool Rect::contains ( const Rect rhs) const

Does rectangle contain other rectangle?

bool Rect::certainClearance ( const Vector v,
double  bound 
) const

Returns false if the distance between the box and v is smaller than bound. Often returns true if their distance is larger than bound.

bool Rect::intersects ( const Rect rhs) const

Does rectangle intersect other rectangle?

Friends And Related Function Documentation

Stream & operator<< ( Stream stream,
const Rect rhs 
)
related

The documentation for this class was generated from the following files:

ipe-7.1.4/build/doc/classipe_1_1_pdf_name.html0000644000175000017500000002513712120621776021014 0ustar otfriedotfried Ipelib: ipe::PdfName Class Reference
Ipelib
Public Member Functions | List of all members
ipe::PdfName Class Reference

#include <ipepdfparser.h>

Inherits ipe::PdfObj.

Public Member Functions

 PdfName (const String &val)
virtual const PdfNamename () const
virtual void write (Stream &stream) const
String value () const
- Public Member Functions inherited from ipe::PdfObj
virtual ~PdfObj ()=0
virtual const PdfNullnull () const
virtual const PdfBoolboolean () const
virtual const PdfNumbernumber () const
virtual const PdfStringstring () const
virtual const PdfRefref () const
virtual const PdfArrayarray () const
virtual const PdfDictdict () const
String repr () const

Detailed Description

The PDF name object.

Constructor & Destructor Documentation

ipe::PdfName::PdfName ( const String val)
inlineexplicit

Member Function Documentation

const PdfName * PdfName::name ( ) const
virtual

Return this object as PDF name object.

Reimplemented from ipe::PdfObj.

void PdfName::write ( Stream stream) const
virtual

Implements ipe::PdfObj.

String ipe::PdfName::value ( ) const
inline

The documentation for this class was generated from the following files:

ipe-7.1.4/build/doc/functions_rela.html0000644000175000017500000000544612120621776017734 0ustar otfriedotfried Ipelib: Class Members - Related Functions
Ipelib
 

ipe-7.1.4/build/doc/classipe_1_1_xml_attributes-members.html0000644000175000017500000001243312120621776023734 0ustar otfriedotfried Ipelib: Member List
Ipelib
ipe::XmlAttributes Member List

This is the complete list of members for ipe::XmlAttributes, including all inherited members.

add(String key, String val)ipe::XmlAttributes
begin() const ipe::XmlAttributesinline
clear()ipe::XmlAttributes
const_iterator typedefipe::XmlAttributes
end() const ipe::XmlAttributesinline
has(String str) const ipe::XmlAttributes
has(String str, String &val) const ipe::XmlAttributes
operator[](String str) const ipe::XmlAttributes
setSlash()ipe::XmlAttributesinline
slash() const ipe::XmlAttributesinline
XmlAttributes()ipe::XmlAttributes

ipe-7.1.4/build/doc/manual_39.html0000644000175000017500000001071412120621776016503 0ustar otfriedotfried Ipe Manual -- 8.5 Unicode text
8.6 Customizing Ipe8 Advanced topics8.4 Using Truetype fonts8.5 Unicode text

8.5 Unicode text

If you make figures containing text objects in languages other than English, you will need to enter accented characters, or characters from other scripts such as Greek, Hangul, Kana, or Chinese characters. Of course you can still use the LaTeX syntax K\"onig to enter the German word "König", but for larger runs of text it's more convenient to enter text in a script supported by your system. When Ipe writes the Pdflatex source file, it writes the text in UTF-8 encoded Unicode. You only have to make sure that Pdflatex can handle this file.

An easy solution, sufficient for German, French, and other languages for which support is already in a standard LaTeX-setup, is to add the line

\usepackage[utf8]{inputenc}
in your Latex preamble (set in the Document properties dialog, available on the Edit menu).

When setting this up, you have to keep in mind that Ipe can only handle scalable fonts, such as Postscript Type1 fonts. You'll have to choose a setup that uses such scalable fonts.

For instance, to use UTF-8 encoded Russian in LaTeX, it is sufficient to put this in the preamble:

\usepackage[utf8]{inputenc}
\usepackage[russian]{babel}
However, this will not work with Ipe: This setup uses Metafont fonts, which are included in the PDF output as bitmaps, and Ipe cannot use these fonts. In this case the solution is to install the PsCyr package, and the following preamble:
\usepackage[utf8]{inputenc}
\usepackage[russian]{babel}
\usepackage{pscyr}

For some languages a LaTeX-setup is available that does not support UTF-8. For instance, Korean Hangul can be typeset using the hfont package, but this requires that the input file is encoded in the EUC-KR encoding. Ipe can convert the LaTeX source to a desired encoding if this is specified in a style sheet. For instance, the following style sheet would enable the use of Korean in the Ipe document:

<ipestyle name="hangul">
<preamble encoding="euc-kr">
\usepackage{hfont}
</preamble>
</ipestyle>
ipe-7.1.4/build/doc/classipe_1_1_ipelet_helper-members.html0000644000175000017500000001202212120621776023501 0ustar otfriedotfried Ipelib: Member List
Ipelib
ipe::IpeletHelper Member List

This is the complete list of members for ipe::IpeletHelper, including all inherited members.

EDiscardCancelButtons enum valueipe::IpeletHelper
EOkButton enum valueipe::IpeletHelper
EOkCancelButtons enum valueipe::IpeletHelper
ESaveDiscardCancelButtons enum valueipe::IpeletHelper
EYesNoCancelButtons enum valueipe::IpeletHelper
getString(const char *prompt, String &str)=0ipe::IpeletHelperpure virtual
message(const char *msg)=0ipe::IpeletHelperpure virtual
messageBox(const char *text, const char *details, int buttons)=0ipe::IpeletHelperpure virtual
~IpeletHelper()=0ipe::IpeletHelperpure virtual

ipe-7.1.4/build/doc/functions_eval.html0000644000175000017500000004611112120621776017732 0ustar otfriedotfried Ipelib: Class Members - Enumerator
Ipelib
 

- e -


ipe-7.1.4/build/doc/structipe_1_1_text_padding.html0000644000175000017500000001162512120621776022131 0ustar otfriedotfried Ipelib: ipe::TextPadding Struct Reference
Ipelib
Public Attributes | List of all members
ipe::TextPadding Struct Reference

#include <ipeattributes.h>

Public Attributes

double iLeft
double iRight
double iTop
double iBottom

Detailed Description

Padding for text bounding box.

Member Data Documentation

double ipe::TextPadding::iLeft
double ipe::TextPadding::iRight
double ipe::TextPadding::iTop
double ipe::TextPadding::iBottom

The documentation for this struct was generated from the following file:

ipe-7.1.4/build/doc/structipe_1_1_text_padding-members.html0000644000175000017500000000627312120621776023564 0ustar otfriedotfried Ipelib: Member List
Ipelib
ipe::TextPadding Member List

This is the complete list of members for ipe::TextPadding, including all inherited members.

iBottomipe::TextPadding
iLeftipe::TextPadding
iRightipe::TextPadding
iTopipe::TextPadding

ipe-7.1.4/build/doc/structipe_1_1_canvas_base_1_1_style.html0000644000175000017500000002015212120621776023577 0ustar otfriedotfried Ipelib: ipe::CanvasBase::Style Struct Reference
Ipelib
Public Attributes | List of all members
ipe::CanvasBase::Style Struct Reference

#include <ipecanvas.h>

Public Attributes

Color paperColor
bool pretty
bool classicGrid
double thinLine
double thickLine
int thinStep
int thickStep
bool paperClip
bool numberPages

Detailed Description

In pretty display, no dashed lines are drawn around text objects, and if Latex font data is not available, no text is drawn at all.

Member Data Documentation

Color ipe::CanvasBase::Style::paperColor
bool ipe::CanvasBase::Style::pretty
bool ipe::CanvasBase::Style::classicGrid
double ipe::CanvasBase::Style::thinLine
double ipe::CanvasBase::Style::thickLine
int ipe::CanvasBase::Style::thinStep
int ipe::CanvasBase::Style::thickStep
bool ipe::CanvasBase::Style::paperClip
bool ipe::CanvasBase::Style::numberPages

The documentation for this struct was generated from the following file:

ipe-7.1.4/build/doc/classipe_1_1_pdf_array-members.html0000644000175000017500000001511512120621776022635 0ustar otfriedotfried Ipelib: Member List
Ipelib
ipe::PdfArray Member List

This is the complete list of members for ipe::PdfArray, including all inherited members.

append(const PdfObj *)ipe::PdfArray
array() const ipe::PdfArrayvirtual
boolean() const ipe::PdfObjvirtual
count() const ipe::PdfArrayinline
dict() const ipe::PdfObjvirtual
name() const ipe::PdfObjvirtual
null() const ipe::PdfObjvirtual
number() const ipe::PdfObjvirtual
obj(int index, const PdfFile *file) const ipe::PdfArray
PdfArray()ipe::PdfArrayinlineexplicit
ref() const ipe::PdfObjvirtual
repr() const ipe::PdfObj
string() const ipe::PdfObjvirtual
write(Stream &stream) const ipe::PdfArrayvirtual
~PdfArray()ipe::PdfArray
~PdfObj()=0ipe::PdfObjpure virtual

ipe-7.1.4/build/doc/modules.html0000644000175000017500000000724412120621776016367 0ustar otfriedotfried Ipelib: Modules
Ipelib
Modules
Here is a list of all modules:
oIpe AttributesAttributes for Ipe objects
oIpe BaseBasic classes for Ipe
oIpe DocumentThe classes managing an Ipe document
oIpe GeometryGeometric primitives for Ipe
oIpe ObjectsThe Ipe object model
oIpe UtilitiesClasses to manage Ipe documents and objects
oThe Ipelet interfaceImplementation of Ipe plugins
oIpe Cairo interfaceDrawing Ipe objects using the Cairo library
\Ipe canvasA widget (control) that displays an Ipe document page

ipe-7.1.4/build/doc/classipe_1_1_curve_segment.html0000644000175000017500000006072212120621776022110 0ustar otfriedotfried Ipelib: ipe::CurveSegment Class Reference
Ipelib
Public Types | Public Member Functions | Friends | List of all members
ipe::CurveSegment Class Reference

#include <ipeshape.h>

Public Types

enum  Type {
  EArc, ESegment, EQuad, EBezier,
  ESpline
}

Public Member Functions

Type type () const
int countCP () const
Vector cp (int i) const
Vector last () const
Matrix matrix () const
Bezier bezier () const
Arc arc () const
void beziers (std::vector< Bezier > &bez) const
void draw (Painter &painter) const
void addToBBox (Rect &box, const Matrix &m, bool cp) const
double distance (const Vector &v, const Matrix &m, double bound) const
void snapVtx (const Vector &mouse, const Matrix &m, Vector &pos, double &bound) const
void snapBnd (const Vector &mouse, const Matrix &m, Vector &pos, double &bound) const

Friends

class Curve

Detailed Description

A segment on an SubPath.

A segment is either an elliptic arc, a straight segment, a quadratic Bezier spline, a cubic Bezier spline, or a B-spline curve, depending on its type(). This is a lightweight object, created on the fly by Curve::segment(). There is no public constructor, so the only way to create such an object is through that method.

The type() is one of the following:

Member Enumeration Documentation

Enumerator:
EArc 
ESegment 
EQuad 
EBezier 
ESpline 

Member Function Documentation

Type ipe::CurveSegment::type ( ) const
inline

Type of segment.

int ipe::CurveSegment::countCP ( ) const
inline

Number of control points.

Vector ipe::CurveSegment::cp ( int  i) const
inline

Return control point.

Vector ipe::CurveSegment::last ( ) const
inline

Return last control point.

Matrix ipe::CurveSegment::matrix ( ) const
inline

Matrix (if Type() == EArc).

Bezier CurveSegment::bezier ( ) const

Return segment as Bezier.

Panics if segment is not a quadratic or cubic Bezier spline.

Arc CurveSegment::arc ( ) const

Return segment as Arc.

Panics if segment is not an arc.

void CurveSegment::beziers ( std::vector< Bezier > &  bez) const

Convert B-spline to a sequence of Bezier splines.

void CurveSegment::draw ( Painter painter) const

Draw the segment.

Current position of the painter is already on first control point.

void CurveSegment::addToBBox ( Rect box,
const Matrix m,
bool  cpf 
) const

Add segment to bounding box.

Does not assume that first control point has already been added.

If cpf is true, then control points of splines, Bezier curves, and the center of arcs are included in the bbox (so that snapping can find them). Otherwise, a tight bounding box for the geometric object itself is computed.

double CurveSegment::distance ( const Vector v,
const Matrix m,
double  bound 
) const

Return distance to the segment.

void CurveSegment::snapVtx ( const Vector mouse,
const Matrix m,
Vector pos,
double &  bound 
) const

Snap to vertex of the segment.

The method assumes that the first control point has already been tested.

void CurveSegment::snapBnd ( const Vector mouse,
const Matrix m,
Vector pos,
double &  bound 
) const

Friends And Related Function Documentation

friend class Curve
friend

The documentation for this class was generated from the following files:

ipe-7.1.4/build/doc/functions_func_0x6d.html0000644000175000017500000001771012120621776020602 0ustar otfriedotfried Ipelib: Class Members - Functions
Ipelib
 

- m -


ipe-7.1.4/build/doc/classipe_1_1_pdf_number.html0000644000175000017500000002465012120621776021363 0ustar otfriedotfried Ipelib: ipe::PdfNumber Class Reference
Ipelib
Public Member Functions | List of all members
ipe::PdfNumber Class Reference

#include <ipepdfparser.h>

Inherits ipe::PdfObj.

Public Member Functions

 PdfNumber (double val)
virtual const PdfNumbernumber () const
virtual void write (Stream &stream) const
double value () const
- Public Member Functions inherited from ipe::PdfObj
virtual ~PdfObj ()=0
virtual const PdfNullnull () const
virtual const PdfBoolboolean () const
virtual const PdfStringstring () const
virtual const PdfNamename () const
virtual const PdfRefref () const
virtual const PdfArrayarray () const
virtual const PdfDictdict () const
String repr () const

Detailed Description

The PDF number object.

Constructor & Destructor Documentation

ipe::PdfNumber::PdfNumber ( double  val)
inlineexplicit

Member Function Documentation

const PdfNumber * PdfNumber::number ( ) const
virtual

Return this object as PDF number object.

Reimplemented from ipe::PdfObj.

void PdfNumber::write ( Stream stream) const
virtual

Implements ipe::PdfObj.

double ipe::PdfNumber::value ( ) const
inline

The documentation for this class was generated from the following files:

ipe-7.1.4/build/doc/classipe_1_1_iml_parser-members.html0000644000175000017500000002500112120621776023016 0ustar otfriedotfried Ipelib: Member List
Ipelib
ipe::ImlParser Member List

This is the complete list of members for ipe::ImlParser, including all inherited members.

eos()ipe::XmlParserinline
Errors enum nameipe::ImlParser
ESuccess enum valueipe::ImlParser
ESyntaxError enum valueipe::ImlParser
EVersionTooOld enum valueipe::ImlParser
EVersionTooRecent enum valueipe::ImlParser
getChar()ipe::XmlParserinline
iChipe::XmlParserprotected
ImlParser(DataSource &source)ipe::ImlParserexplicit
iPosipe::XmlParserprotected
iSourceipe::XmlParserprotected
isTagChar(int ch)ipe::XmlParserinline
iTopElementipe::XmlParserprotected
parseAttributes(XmlAttributes &attr, bool qm=false)ipe::XmlParser
parseBitmap()ipe::ImlParser
parseDocument(Document &doc)ipe::ImlParser
parseFontmap(String *stdNames, String *paths)ipe::ImlParser
parseObject(String tag, Page *page=0, int *currentLayer=0)ipe::ImlParser
parsePage(Page &page)ipe::ImlParser
parsePageSelection()ipe::ImlParser
parsePCDATA(String tag, String &pcdata)ipe::XmlParser
parsePosition() const ipe::XmlParserinline
parseStyle(StyleSheet &sheet)ipe::ImlParser
parseStyleSheet()ipe::ImlParser
parseToTag()ipe::XmlParser
parseToTagX()ipe::XmlParserprotected
pdfStream(int objNum)ipe::ImlParservirtual
skipWhitespace()ipe::XmlParser
XmlParser(DataSource &source)ipe::XmlParser
~XmlParser()ipe::XmlParservirtual

ipe-7.1.4/build/doc/manual_24.html0000644000175000017500000001305012120621776016471 0ustar otfriedotfried Ipe Manual -- 5.3 Angular snapping
5.4 Interaction of the snapping modes5 Snapping5.2 Context snapping5.3 Angular snapping

5.3 Angular snapping

When angular snapping is enabled, the mouse position is restricted to lie on a set of lines through the origin of your current axis system. The lines are the lines whose angle with the base direction is an integer multiple of the snap angle. The snap angle can be set in the second box in the Snap toolbar. The values are indicated in degrees.

For a snap angle of 180 degrees, snapping is to a single line through the current origin.

In order to use angular snapping, it is important to set the axis system correctly. To set the origin, move the mouse to the correct position, and press the F1-key. Note that angular snapping is disabled while setting the origin. This way you can set a new origin for angular snapping without leaving the mode first. Once the origin has been set, the base direction is set by moving to a point on the desired base line, and pressing the F2-key. Again, angular snapping is disabled. Together, origin and base direction determine the current axis system. Remember that the origin is also used as the fix-point of scale, stretch, and rotate operations, if it is set.

You can un-set the current axis system by pressing Shift-F2. This also turns off angular snapping. You can set origin and base direction at the same time by pressing F3 when the mouse is very near (or snapped to) an edge of a polygonal object. The origin is set to an endpoint of the edge, and the base direction is aligned with it. This is useful to make objects parallel to a given edge.

For drawing rectilinear or c-oriented polygons, the origin should be set to the previous vertex at every step. This can be done by pressing F1 every time you click the left mouse button, but that would not be very convenient. Therefore, Ipe offers a second angular snap mode, called automatic angular snapping. This mode uses an independent origin, which is automatically set every time you add a vertex when creating a polygonal object. Note that while the origin is independent of the origin set by F1, the base direction and the snap angle used by automatic angular snapping is the same as for angular snapping. Hence, you can align the axis system with some edge of your drawing using F3, and then use automatic angular snapping to draw a new object that is parallel or orthogonal to this edge.

This snapping mode has another advantage: It remains silent and ineffective until you start creating a polygonal object. So, even with automatic angular snapping already turned on, you can still freely place the first point of a polygon, and then the remaining vertices will be properly aligned to make a c-oriented polygon.

The automatic angular snapping mode is never active for any non-polygonal object. In particular, to move an object in a prescribed direction, you have to use normal angular snapping.

A final note: Many things that can be done with angular snapping can also be done by drawing auxiliary lines and using context snapping. It is mostly a matter of taste and exercise to figure out which mode suits you best.

ipe-7.1.4/build/doc/classipe_1_1_symbol-members.html0000644000175000017500000001016112120621776022167 0ustar otfriedotfried Ipelib: Member List
Ipelib
ipe::Symbol Member List

This is the complete list of members for ipe::Symbol, including all inherited members.

iObjectipe::Symbol
iTransformationsipe::Symbol
iXFormipe::Symbol
operator=(const Symbol &rhs)ipe::Symbol
Symbol()ipe::Symbol
Symbol(Object *object)ipe::Symbol
Symbol(const Symbol &rhs)ipe::Symbol
~Symbol()ipe::Symbol

ipe-7.1.4/build/doc/polygon.pdf0000644000175000017500000001037112120621776016206 0ustar otfriedotfried%PDF-1.3 3 0 obj << /Length 196 /Filter /FlateDecode >> stream xÚ-»mƒ1 „{MÁ ¾)NÀ]’!bv‘*ëçôÕÀ;ò;Дë—”þ–`þúXJ?K«9µH»XÆéµrsõN²Þô\&ÃÞE¾¯Açšcœ¹¡¸ç.(ÁæåxžAá›§J:²ÊÉlqÈ‘Í:J¶×z8Øvi\9O޶3‘n,Ñ—Ò<Ø6 8ç*E¸ -À{“©ÙTyÀW mî:F×ʼn¹þ£=qzi£O‹`¸Ó÷ú\ÿêü>Œ endstream endobj 4 0 obj << /Type /Page /Contents 3 0 R /Resources << /ProcSet [ /PDF ] >> /MediaBox [ 0 0 595 842] /ArtBox [58.0785 64.9814 538.163 494.833] /Parent 2 0 R >> endobj 5 0 obj << /Length 262 /Filter /FlateDecode >> stream xÚR;N1 ìs ŸÀòßñ è€Ñ!T\gE/û$ªUlÏŒg¼·Àð6>QàkP¿ïoÃËàHtà ¤Rø>1r:ˆN6xB…š:©¿Ò•RœÆV‚î³+*>£+†¢Ú•ÕS70X™]qm­P©–XÌæ‰\ 2¹Ñ¼xzZ)¥X¾x$zÚ½ÕÉò¨$VO‹Xwʉ0¥]4ßs¶ª'„/âÃ'¦¬FÆÁcuìÃYh¶|q¶%êÇ+<Œ»NíÑž:±çAhÞ íÒþÇÉÚ×°—Aa÷èö þ¿ÛI€ÛAÿßÿ€kb¿`§:[ÀûéNµ¡–ü7Q+ŒÔ endstream endobj 6 0 obj << /Type /Page /Contents 5 0 R /Resources << /ProcSet [ /PDF ] >> /MediaBox [ 0 0 595 842] /ArtBox [58.0785 64.9814 538.163 494.833] /Parent 2 0 R >> endobj 7 0 obj << /Length 1261 /Filter /FlateDecode >> stream xÚW½Î,5 íç)RSD‰óÿHt@‰¨BLqix}Ž'±3Éî7¢ÚµçøØN;qæãÍ_Ç7ã-™g䟾?¼ùãð¹Øä³ñ%[ׂ9Tm.5JÍVÍß¹fCÉ&T‡_‚¦[£O&6²)Uhe›j†&Z þR41TÛJ&øÊÁ5¸`昊õͪ֞y€®À*Ø–˜‡2Ð)Á;YË¥)¶Mñ…­’s¶²ß`.ðšŠÉ‰‰¯,|±%6ÃJ¾xb»âñ¥Ù9/_O4Á9šŸ±j¿Ä_±b¿ÎF¬/Úžþù!ì¯l÷…údû¾tï õÿcû°€oº$þ^_9»™}ôó¶Àï[÷a£Þ¬ºûoFsÿƒTóžêÔ`qñÛ’­b!ñ‡sqºü:`êkÌá6·ú€…jœmÎe¨mõ1dXH‚ÈCÞ}üþ2þ˜3Çy/sj¢³9Ä+rÆè/€ÖÒ_»Í­LÂZD.`¡šb%iu1dvÑcP@ZíÓæàë|}I³ÂTð(ž‚‰8(cÇÅ2*1€ÎìQ ýªòn#¢c\¨áFæèfÔŠðñ_æëŽú‡´Ú¤É÷–7Ú+ J´Ôô958Ñ®56tg‚H@Á_88:.ßy%y¸` Ñ óñyôúÅÇa1‚€F=¶,ž2¨®g½«EîsªI6{oBh¶-†|!zÌ*¿Ð36íHAZ\°hÈòf)Û<85Bc[O'œŸûx;§&€%x“à<¶ ìŒÐ8äFdº¶h"âÆl!šŠ#WŒ2`Î,>†Ì# Ah܃aËãcΜ5·£ì–¹tÞ4󭚈iR1 ¨Æ 1'Y—Ñ,ŽúÎDÄ!.>ØbhP‡ÐH„³dñ1d¶QB¢†-§œÖe›àªI¶6°¹Ï• 0G~—QvÚ V‚°x`ÑàòäV¿¹ðj!A¢m móñн<-÷…ó¦Á¬GäÑ„Ø öŒó†Ñe´‡B7@^ Tvj04ز‚é(èE‹‡!Ã@b„Ä([O{Lhÿ÷»ÌyÓ[×N¤ç„Ò…˜·Ÿ.¿ú]y"òÊ 2©…h!ÖDP¤‹‹!Ã@‚„Ù ¶,ž2Î~½ôSƒ?±xƒ#xlS¦ ¡×Ä!£³ì%ŠH+ƒÊÃ,TS-.ïFR^} ùuhC3ãî {OuÍ}üL Š-]·Ü®Ç€ùZê2_!pbS»!âJl šh1ØÌ$›‹ Ä@hŒƒaËâqF¹°<”Λ¦õ ãpJ*¼a¡¯é O«!ó婿¦nbw†)µM¾&Œ2 />†Œº(†=§+$a}îoŽó¦A‹qµ,L¢r!æ+¥ËýdJ7DÜââƒ-DC8Äý´w¿ùðj!Q „F9¶<s&·ØbhЀ}C&ƒ¡¤Õ‡ÈlÑ£P„Ä- [wôö’<§†§,.ö‘CçžQ;BßžCF¥²c¼\&"­ "§i14/¸k m>H-$ AH”°å¡9ÿPÚz endstream endobj 8 0 obj << /Type /Page /Contents 7 0 R /Resources << /ProcSet [ /PDF ] >> /MediaBox [ 0 0 595 842] /ArtBox [54.9785 61.8814 541.263 497.933] /Parent 2 0 R >> endobj 1 0 obj << /Type /Ipe /Length 1194 /Filter /FlateDecode >> stream xÚÅXMoã6½çWº[懾\Ä hÑ=ì©×ºÆ¡m!”èJtwÑÿÞ!%Ë”Dmgï9|œ÷8 ©Üç{žEUçª\)†ZW‚kU-Ô ~‚/w÷y¹Q͈x\¿ýB1ŽpŒ%ã,@…zÌ7y7–JJ£Œ°íùVÀ¸X›ƒ”5xe07N÷¢ÖG) Y‹%QÉ €¼zš¯ój--÷žëÚäR.€Íj]©' ˼Ü.ƒRU—Äa‚°ùß>X¢Öµ–û¹ñNç £—ú1¯×#¾ˆfsâÙVê°Ÿæ3–ê ašP¦ýÑ¥h&]NÇî$øG«{P¯Á‡Ö43‹±?Å]×”ÍRmkvnîL'Bö§¸ëš²Y…mÍÎÍÝeûSÿsàÕ»2ð}’/K’³Š§É{ôá+¢yYf]»U—dݺRu}A°¼¢˜‘§V<¬ÅêbȬ2xÎÚ‘é•¿Aã²Ì\šYgLã‰Á^”mv‚?ç¢ Ð3—èã0³eöŒØpÝ’FRWÜ…4€†©Îÿ-Nòj+:PìÕ°^ù–'—GG±(^Uêe’Ž`/¨O{1=6f!k%UÕWâñÌbJÞ±µ'W^D<˜s AŽBJõâp/?g+ ½ê`& ̰ԉŒ;ˆd‚)q0D©›ž-æ‘×;{hq¦ïlÆ_Ñßm€F@¥µ $ˆMB¡†øQ>}kÎÔîñ&Ž·ì³ôc3N…qjö·q”ËŸ%Ö¥õ ç›'‹G9;žÕé?Ôâ””mÍøÑbàªYÖ#V窄’c ²é£¯q´W€l„JlwØžâc.róVÐO—0È¿[Hpvözˆ]’bhD±Ù\v¥ŠA¶L(ÙvìñjI`†Ñn¯°¦+µ ÇuZ>º-ƒÃä6"ÅpB„=ƒ?MÃe»ñ¹eø6›1(º7 Dÿ¼¹Í^ô/t7z1ú²[%Ä%5ósó¥ó&ÇgÿFñV>ÎÛ¯%óõåîü‘M¹ endstream endobj 2 0 obj << /Type /Pages /Count 3 /Kids [ 4 0 R 6 0 R 8 0 R ] >> endobj 9 0 obj << /Type /Catalog /Pages 2 0 R /PageMode /FullScreen /PageLabels << /Nums [ 0 <>] >> >> endobj 10 0 obj << /Creator (ipetoipe) /Producer (ipetoipe) /CreationDate (D:20040503211008) /ModDate (D:20061216224813) >> endobj xref 0 11 0000000000 00000 f 0000002455 00000 n 0000003733 00000 n 0000000009 00000 n 0000000277 00000 n 0000000447 00000 n 0000000781 00000 n 0000000951 00000 n 0000002285 00000 n 0000003804 00000 n 0000003922 00000 n trailer << /Size 11 /Root 9 0 R /Info 10 0 R >> startxref 4046 %%EOF ipe-7.1.4/build/doc/classipe_1_1_pdf_ref.html0000644000175000017500000002457612120621776020656 0ustar otfriedotfried Ipelib: ipe::PdfRef Class Reference

#include <ipepdfparser.h>

Inherits ipe::PdfObj.

Public Member Functions

 PdfRef (int val)
virtual const PdfRefref () const
virtual void write (Stream &stream) const
int value () const
- Public Member Functions inherited from ipe::PdfObj
virtual ~PdfObj ()=0
virtual const PdfNullnull () const
virtual const PdfBoolboolean () const
virtual const PdfNumbernumber () const
virtual const PdfStringstring () const
virtual const PdfNamename () const
virtual const PdfArrayarray () const
virtual const PdfDictdict () const
String repr () const

Detailed Description

The PDF reference object (indirect object).

Constructor & Destructor Documentation

ipe::PdfRef::PdfRef ( int  val)
inlineexplicit

Member Function Documentation

const PdfRef * PdfRef::ref ( ) const
virtual

Return this object as PDF reference object.

Reimplemented from ipe::PdfObj.

void PdfRef::write ( Stream stream) const
virtual

Implements ipe::PdfObj.

int ipe::PdfRef::value ( ) const
inline

The documentation for this class was generated from the following files:
  • ipepdfparser.h
  • ipepdfparser.cpp

ipe-7.1.4/build/doc/hierarchy.html0000644000175000017500000011670312120621776016676 0ustar otfriedotfried Ipelib: Class Hierarchy
Class Hierarchy
This inheritance list is sorted roughly, but not completely, alphabetically:
[detail level 123]
oCipe::AllAttributesCollection of all object attributes
oCipe::AngleA double that's an angle
oCipe::ArcAn arc of an ellipse
oCipe::AttributeAn attribute of an Ipe Object
oCipe::BezierA cubic Bezier spline
oCipe::BitmapA bitmap
oCipe::BufferA memory buffer
oCipe::CanvasBase
oCipe::CanvasObserver
oCipe::CascadeA cascade of style sheets
oCipe::ColorAn absolute RGB color
oCipe::CurveSegmentA segment on an SubPath
oCipe::DataSourceInterface for getting data for parsing
oCipe::DocumentThe model for an Ipe document
oCipe::EffectEffect that Acrobat Reader will show on page change
oCipe::FaceA typeface (aka font), actually loaded (from a font file or PDF file)
oCipe::FixedFixed point number with three (decimal) fractional digits
oCipe::FontA text font
oCipe::FontsProvides the fonts used to render text
oCipe::GradientA gradient pattern
oCIpeAutoPtr< T >
oCipe::IpeletAbstract base class for Ipelets
oCipe::IpeletDataInformation provided to an ipelet when it is run
oCipe::IpeletHelperService provider for Ipelets
oCipe::LatexObject that converts latex source to PDF format
oCipe::LayoutLayout of a Page
oCipe::LexLexical analyser. Seeded with a string
oCipe::LineA directed line
oCipe::LinearLinear transformation in the plane (2x2 matrix)
oCipe::MatrixHomogeneous transformation in the plane
oCipe::Bitmap::MRenderDataAbstract base class for pixmap data stored by a client
oCipe::ObjectBase class for all Ipe objects, composite or leaf
oCipe::ObjectFactoryFactory for Ipe leaf objects
oCipe::PageAn Ipe document page
oCipe::StyleSheet::PageNumberStyleHow to show page numbers on the paper
oCipe::PageSelector
oCipe::PainterInterface for drawing
oCipe::PdfFileAll information obtained by parsing a PDF file
oCipe::PdfObjAbstract base class for PDF objects
oCipe::PdfParserPDF parser
oCipe::PdfTokenA PDF lexical token
oCipe::PdfWriterCreate PDF file
oCipe::PlatformPlatform dependent methods
oCipe::PsWriterCreate Postscript file
oCipe::RectAxis-parallel rectangle (which can be empty)
oCipe::RepositoryRepository of strings
oCipe::SegmentA directed line segment
oCipe::ShapeA geometric shape, consisting of several (open or closed) subpaths
oCipe::SnapPerforms snapping operations, and stores snapping state
oCipe::SelectTool::SObj
oCipe::Document::SPropertiesProperties of a document
oCipe::Painter::State
oCipe::Gradient::StopA color stop
oCipe::StreamAbstract base class for output streams
oCipe::StringStrings and buffers
oCipe::CanvasBase::Style
oCipe::StyleSheetA style sheet maps symbolic names to absolute values
oCipe::SubPathA subpath of a Path
oCipe::SymbolA symbol is a named object defined in an ipe::StyleSheet
oCipe::TextPaddingPadding for text bounding box
oCipe::Thumbnail
oCipe::TilingA tiling pattern
oCipe::StyleSheet::TitleStyleStyle of the title on a page
oCipe::ToolAbstract base class for various canvas tools
oCipe::VectorTwo-dimensional vector
oCipe::VisitorBase class for visitors to Object
oCipe::Text::XForm
oCipe::XmlAttributesStores attributes of an XML tag
\Cipe::XmlParserBase class for XML stream parsing

ipe-7.1.4/build/doc/functions_func_0x65.html0000644000175000017500000001417212120621776020522 0ustar otfriedotfried Ipelib: Class Members - Functions
 

- e -


ipe-7.1.4/build/doc/classipe_1_1_canvas_base-members.html0000644000175000017500000006252012120621776023135 0ustar otfriedotfried Ipelib: Member List
ipe::CanvasBase Member List

This is the complete list of members for ipe::CanvasBase, including all inherited members.

additionalModifiers() const ipe::CanvasBaseinline
CanvasBase()ipe::CanvasBaseprotected
canvasHeight() const ipe::CanvasBaseinline
canvasStyle() const ipe::CanvasBaseinline
canvasTfm() const ipe::CanvasBase
canvasWidth() const ipe::CanvasBaseinline
cascade() const ipe::CanvasBaseinline
center() const ipe::CanvasBaseinline
computeFifi(double x, double y)ipe::CanvasBaseprotected
devToUser(const Vector &arg) const ipe::CanvasBase
drawAxes(cairo_t *cc)ipe::CanvasBaseprotected
drawFrame(cairo_t *cc)ipe::CanvasBaseprotected
drawGrid(cairo_t *cc)ipe::CanvasBaseprotected
drawObjects(cairo_t *cc)ipe::CanvasBaseprotected
drawPaper(cairo_t *cc)ipe::CanvasBaseprotected
drawTool(Painter &painter)ipe::CanvasBaseprotected
EAlt enum valueipe::CanvasBase
EControl enum valueipe::CanvasBase
ECrossCursor enum valueipe::CanvasBase
EDotCursor enum valueipe::CanvasBase
EHandCursor enum valueipe::CanvasBase
EMeta enum valueipe::CanvasBase
EShift enum valueipe::CanvasBase
EStandardCursor enum valueipe::CanvasBase
finishTool()ipe::CanvasBase
globalPos() const ipe::CanvasBaseinline
iAdditionalModifiersipe::CanvasBaseprotected
iAutoOriginipe::CanvasBaseprotected
iAutoSnapipe::CanvasBaseprotected
iCascadeipe::CanvasBaseprotected
iDimmedipe::CanvasBaseprotected
iFifiVisibleipe::CanvasBaseprotected
iFontsipe::CanvasBaseprotected
iGlobalPosipe::CanvasBaseprotected
iHeightipe::CanvasBaseprotected
iMousePosipe::CanvasBaseprotected
invalidate()=0ipe::CanvasBaseprotectedpure virtual
invalidate(int x, int y, int w, int h)=0ipe::CanvasBaseprotectedpure virtual
iObserveripe::CanvasBaseprotected
iOldFifiipe::CanvasBaseprotected
iPageipe::CanvasBaseprotected
iPageNumberipe::CanvasBaseprotected
iPanipe::CanvasBaseprotected
iRepaintObjectsipe::CanvasBaseprotected
iSelectionVisibleipe::CanvasBaseprotected
iSnapipe::CanvasBaseprotected
iStyleipe::CanvasBaseprotected
iSurfaceipe::CanvasBaseprotected
iToolipe::CanvasBaseprotected
iUnsnappedMousePosipe::CanvasBaseprotected
iViewipe::CanvasBaseprotected
iWidthipe::CanvasBaseprotected
iZoomipe::CanvasBaseprotected
pan() const ipe::CanvasBaseinline
pos() const ipe::CanvasBaseinline
refreshSurface()ipe::CanvasBaseprotected
setAdditionalModifiers(int mod)ipe::CanvasBase
setAutoOrigin(const Vector &v)ipe::CanvasBase
setCanvasStyle(const Style &style)ipe::CanvasBase
setCursor(TCursor cursor, double w=1.0, Color *color=0)=0ipe::CanvasBasepure virtual
setDimmed(bool dimmed)ipe::CanvasBase
setFifiVisible(bool visible)ipe::CanvasBase
setFontPool(const FontPool *fontPool)ipe::CanvasBase
setObserver(CanvasObserver *observer)ipe::CanvasBase
setPage(const Page *page, int pno, int view, const Cascade *sheet)ipe::CanvasBase
setPan(const Vector &v)ipe::CanvasBase
setSelectionVisible(bool visible)ipe::CanvasBase
setSnap(const Snap &s)ipe::CanvasBase
setTool(Tool *tool)ipe::CanvasBase
setZoom(double zoom)ipe::CanvasBase
simpleSnapPos() const ipe::CanvasBase
snap() const ipe::CanvasBaseinline
snapToPaperAndFrame()ipe::CanvasBaseprotected
TCursor enum nameipe::CanvasBase
TModifiers enum nameipe::CanvasBase
unsnappedPos() const ipe::CanvasBaseinline
update()ipe::CanvasBase
updateTool()ipe::CanvasBase
userToDev(const Vector &arg) const ipe::CanvasBase
zoom() const ipe::CanvasBaseinline
~CanvasBase()ipe::CanvasBasevirtual

ipe-7.1.4/build/doc/class_ipe_auto_ptr-members.html0000644000175000017500000000721612120621776022225 0ustar otfriedotfried Ipelib: Member List
IpeAutoPtr< T > Member List

This is the complete list of members for IpeAutoPtr< T >, including all inherited members.

IpeAutoPtr(T *ptr)IpeAutoPtr< T >inline
operator*()IpeAutoPtr< T >inline
operator->()IpeAutoPtr< T >inline
ptr()IpeAutoPtr< T >inline
take()IpeAutoPtr< T >inline
~IpeAutoPtr()IpeAutoPtr< T >inline

ipe-7.1.4/build/doc/classipe_1_1_bitmap.html0000644000175000017500000011032412120621776020510 0ustar otfriedotfried Ipelib: ipe::Bitmap Class Reference

#include <ipebitmap.h>

Classes

struct  Imp
class  MRenderData
 Abstract base class for pixmap data stored by a client. More...

Public Types

enum  TFilter { EDirect, EFlateDecode, EDCTDecode }
enum  TColorSpace { EDeviceRGB, EDeviceGray, EDeviceCMYK }

Public Member Functions

 Bitmap ()
 Bitmap (int width, int height, TColorSpace colorSpace, int bitsPerComponent, Buffer data, TFilter filter, bool deflate=false)
 Bitmap (const XmlAttributes &attr, String data)
 Bitmap (const XmlAttributes &attr, Buffer data)
 Bitmap (const Bitmap &rhs)
 ~Bitmap ()
Bitmapoperator= (const Bitmap &rhs)
void saveAsXml (Stream &stream, int id, int pdfObjNum=-1) const
bool isNull () const
bool equal (Bitmap rhs) const
TColorSpace colorSpace () const
TFilter filter () const
int components () const
int bitsPerComponent () const
int width () const
int height () const
int colorKey () const
void setColorKey (int key)
const char * data () const
int size () const
int objNum () const
void setObjNum (int objNum) const
MRenderDatarenderData () const
void setRenderData (MRenderData *data) const
Buffer pixelData () const
bool operator== (const Bitmap &rhs) const
bool operator!= (const Bitmap &rhs) const
bool operator< (const Bitmap &rhs) const

Detailed Description

A bitmap.

Bitmaps are explicitely shared using reference-counting. Copying is cheap, so Bitmap objects are meant to be passed by value.

The bitmap can cache data to speed up rendering. This data can be set only once (as the bitmap is conceptually immutable).

The bitmap also provides a slot for short-term storage of an "object number". The PDF embedder, for instance, sets it to the PDF object number when embedding the bitmap, and can reuse it when "drawing" the bitmap.

Member Enumeration Documentation

Enumerator:
EDirect 
EFlateDecode 
EDCTDecode 
Enumerator:
EDeviceRGB 
EDeviceGray 
EDeviceCMYK 

Constructor & Destructor Documentation

Bitmap::Bitmap ( )

Default constructor constructs null bitmap.

Bitmap::Bitmap ( int  width,
int  height,
TColorSpace  colorSpace,
int  bitsPerComponent,
Buffer  data,
TFilter  filter,
bool  deflate = false 
)

Create a new image.

Bitmap::Bitmap ( const XmlAttributes attr,
String  data 
)

Create from XML stream.

Bitmap::Bitmap ( const XmlAttributes attr,
Buffer  data 
)

Create from XML using external raw data.

Bitmap::Bitmap ( const Bitmap rhs)

Copy constructor.

Since Bitmaps are reference counted, this is very fast.

Bitmap::~Bitmap ( )

Destructor.

Member Function Documentation

Bitmap & Bitmap::operator= ( const Bitmap rhs)

Assignment operator (takes care of reference counting).

Very fast.

void Bitmap::saveAsXml ( Stream stream,
int  id,
int  pdfObjNum = -1 
) const

Save bitmap in XML stream.

bool ipe::Bitmap::isNull ( ) const
inline

Is this a null bitmap?

bool Bitmap::equal ( Bitmap  rhs) const
Bitmap::TColorSpace ipe::Bitmap::colorSpace ( ) const
inline

Return the color space of the image.

Bitmap::TFilter ipe::Bitmap::filter ( ) const
inline

Return the data filter of the image data.

int ipe::Bitmap::components ( ) const
inline

Return number of components per pixel.

int ipe::Bitmap::bitsPerComponent ( ) const
inline

Return the number of bits per component.

int ipe::Bitmap::width ( ) const
inline

Return width of pixel array.

int ipe::Bitmap::height ( ) const
inline

Return height of pixel array.

int Bitmap::colorKey ( ) const

Return rgb representation of the transparent color.

Returns -1 if the bitmap is not color keyed.

void Bitmap::setColorKey ( int  key)

Set transparent color.

Use key == -1 to disable color key.

const char * ipe::Bitmap::data ( ) const
inline

Return a pointer to the image data (in PDF arrangement).

int ipe::Bitmap::size ( ) const
inline

Return size (number of bytes) of image data (in PDF arrangement).

int ipe::Bitmap::objNum ( ) const
inline

Return object number of the bitmap.

void ipe::Bitmap::setObjNum ( int  objNum) const
inline

Set object number of the bitmap.

Bitmap::MRenderData * ipe::Bitmap::renderData ( ) const
inline

Return cached bitmap for rendering.

void Bitmap::setRenderData ( MRenderData data) const

Set a cached bitmap for fast rendering.

Buffer Bitmap::pixelData ( ) const

Convert bitmap data to a height x width pixel array in rgb format.

Returns empty buffer if it cannot decode the bitmap information. Otherwise, returns a buffer of size Width() * Height() uint's.

bool ipe::Bitmap::operator== ( const Bitmap rhs) const
inline

Two bitmaps are equal if they share the same data.

bool ipe::Bitmap::operator!= ( const Bitmap rhs) const
inline

Two bitmaps are equal if they share the same data.

bool ipe::Bitmap::operator< ( const Bitmap rhs) const
inline

Less operator, to be able to sort bitmaps.

The checksum is used, when it is equal, the shared address. This guarantees that bitmaps that are == (share their implementation) are next to each other, and blocks of them are next to blocks that are identical in contents.


The documentation for this class was generated from the following files:
  • ipebitmap.h
  • ipebitmap.cpp

ipe-7.1.4/build/doc/classipe_1_1_buffer.html0000644000175000017500000003172612120621776020515 0ustar otfriedotfried Ipelib: ipe::Buffer Class Reference

#include <ipebase.h>

Classes

struct  Imp

Public Member Functions

 Buffer ()
 ~Buffer ()
 Buffer (const Buffer &rhs)
Bufferoperator= (const Buffer &rhs)
 Buffer (int size)
 Buffer (const char *data, int size)
char & operator[] (int index)
const char & operator[] (int index) const
int size () const
char * data ()
const char * data () const

Detailed Description

A memory buffer.

Implements sharing semantics using reference counting.

Constructor & Destructor Documentation

Buffer::Buffer ( )

Create empty buffer.

Buffer::~Buffer ( )

Destructor.

Buffer::Buffer ( const Buffer rhs)

Copy constructor. Constant time, buffer is shared.

Buffer::Buffer ( int  size)
explicit

Create buffer of specified size.

Buffer::Buffer ( const char *  data,
int  size 
)
explicit

Create buffer by copying the data.

Member Function Documentation

Buffer & Buffer::operator= ( const Buffer rhs)

Assignment operator (constant-time).

char& ipe::Buffer::operator[] ( int  index)
inline

Character access.

const char& ipe::Buffer::operator[] ( int  index) const
inline

Character access (const version).

int ipe::Buffer::size ( ) const
inline

Return size of buffer;.

char* ipe::Buffer::data ( )
inline

Return pointer to buffer data.

const char* ipe::Buffer::data ( ) const
inline

Return pointer to buffer data (const version).


The documentation for this class was generated from the following files:
  • ipebase.h
  • ipebase.cpp

ipe-7.1.4/build/doc/group__base.html0000644000175000017500000003662012120621776017204 0ustar otfriedotfried Ipelib: Ipe Base
Ipe Base

Classes

class  ipe::String
 Strings and buffers. More...
class  ipe::Fixed
 Fixed point number with three (decimal) fractional digits. More...
class  ipe::Lex
 Lexical analyser. Seeded with a string. More...
class  ipe::Buffer
 A memory buffer. More...
class  ipe::Stream
 Abstract base class for output streams. More...
class  ipe::StringStream
 Stream writing into an String. More...
class  ipe::FileStream
 Stream writing into an open file. More...
class  ipe::DataSource
 Interface for getting data for parsing. More...
class  ipe::FileSource
 Data source for parsing from a file. More...
class  ipe::BufferSource
 Data source for parsing from a buffer. More...
class  ipe::Bitmap::MRenderData
 Abstract base class for pixmap data stored by a client. More...
class  ipe::Bitmap
 A bitmap. More...
class  ipe::Painter
 Interface for drawing. More...
class  ipe::PdfObj
 Abstract base class for PDF objects. More...
class  ipe::PdfNull
 The PDF null object. More...
class  ipe::PdfBool
 The PDF bool object. More...
class  ipe::PdfNumber
 The PDF number object. More...
class  ipe::PdfString
 The PDF string object. More...
class  ipe::PdfName
 The PDF name object. More...
class  ipe::PdfRef
 The PDF reference object (indirect object). More...
class  ipe::PdfArray
 The PDF array object. More...
class  ipe::PdfDict
 The PDF dictionary and stream objects. More...
class  ipe::PdfParser
 PDF parser. More...
class  ipe::PdfFile
 All information obtained by parsing a PDF file. More...
class  ipe::Platform
 Platform dependent methods. More...
class  ipe::XmlAttributes
 Stores attributes of an XML tag. More...
class  ipe::XmlParser
 Base class for XML stream parsing. More...
class  ipe::TellStream
 Adds position feedback to IpeStream. More...

Variables

const int ipe::IPELIB_VERSION = 70104
const int ipe::OLDEST_FILE_FORMAT = 70000
const int ipe::FILE_FORMAT = 70005

Detailed Description

Basic classes for Ipe.

Some very basic type definitions, streams, lexical analysis, and XML parsing.

All parts of Ipe make use of the STL. The C++ I/O streams library is not used, as Ipelib doesn't do much I/O. Ipe objects support internalization and externalization through an abstract interface based on ipe::Stream's.

Clients of Ipelib can use any I/O library that implements this interface. Ipe simply uses cstdio.

Variable Documentation

const int ipe::IPELIB_VERSION = 70104

Ipelib version.

const int ipe::OLDEST_FILE_FORMAT = 70000

Oldest readable file format version.

const int ipe::FILE_FORMAT = 70005

Current file format version.


ipe-7.1.4/build/doc/structipe_1_1_canvas_base_1_1_style-members.html0000644000175000017500000001146012120621776025231 0ustar otfriedotfried Ipelib: Member List
ipe::CanvasBase::Style Member List

ipe-7.1.4/build/doc/classipe_1_1_pan_tool-members.html0000644000175000017500000001065712120621776022507 0ustar otfriedotfried Ipelib: Member List
ipe::PanTool Member List

This is the complete list of members for ipe::PanTool, including all inherited members.

draw(Painter &painter) const ipe::PanToolvirtual
iCanvasipe::Toolprotected
key(int code, int modifiers, String text)ipe::Toolvirtual
mouseButton(int button, bool press)ipe::PanToolvirtual
mouseMove()ipe::PanToolvirtual
PanTool(CanvasBase *canvas, const Page *page, int view)ipe::PanTool
Tool(CanvasBase *canvas)ipe::Toolprotected
~Tool()ipe::Toolvirtual

ipe-7.1.4/build/doc/functions_0x64.html0000644000175000017500000004422212120621776017505 0ustar otfriedotfried Ipelib: Class Members
Here is a list of all class members with links to the classes they belong to:

- d -


ipe-7.1.4/build/doc/ftv2blank.png0000644000175000017500000000012612120621776016420 0ustar otfriedotfried‰PNG  IHDRɪ|IDATxíݱðøScOx@ –¨y}IEND®B`‚ipe-7.1.4/build/doc/tab_b.png0000644000175000017500000000024712120621776015602 0ustar otfriedotfried‰PNG  IHDR$ÇÇ[nIDATxíÝQ Â0„áàœR¥Xc±I7IÓ¨g|òÕÙœäãgY˜3˜Ï÷‡u{£ÔW—ÊSíŒ1Ü ¼CjˆiC†G¬ýççJ+| ÖÝs7ùŒ+Ù›`t‚3Ü‚a¢K¤Gq°ûQÍZÝT=@*éC݇LIEND®B`‚ipe-7.1.4/build/doc/index.html0000644000175000017500000002211512120621776016020 0ustar otfriedotfried Ipelib: The Ipe library documentation
The Ipe library documentation

The Ipe library ("Ipelib") provides the geometric primitives and implements all the geometric objects that appear in Ipe. Many tasks related to modifying an Ipe document are actually performed by Ipelib. For instance, the ipetoipe program consists of only a few calls to Ipelib.

Ipelib can easily be used by C++ programs to read, write, and modify Ipe documents. Compiling Ipelib is easy, it requires only the standard C++ library (including the STL), and the zlib compression library. Nearly all symbols in Ipelib are in the ipe namespace, those that aren't start with the letters "Ipe".

Many of the Ipelib classes are also made available as Lua objects. Programming in Lua describes the Lua bindings to Ipelib, to ipeui, and to the Ipe program itself. The Ipe program itself is mostly written in Lua and uses these Lua bindings.

All filenames passed to Ipelib are assumed to be in the local system's encoding. All Lua strings are assumed to be UTF-8 (filenames are converted by the ipelua bindings).

Ipelets explains how to write ipelets, that is, extensions to Ipe. Ipelets are either written in Lua or in C++ (using a small Lua wrapper to describe the ipelet). C++ ipelets have to be linked with Ipelib to access and modify Ipe objects.

The classes documented here are implemented in five different libraries:

  • libipe is the core Ipelib library. It implements geometric primitives, Ipe objects, and the Ipe document. However, it doesn't know anything about drawing to the screen or about the Lua bindings.
  • libipecairo implements the Ipe cairo module. It provides drawing of Ipe objects using the Cairo library.
  • libipelua implements the Lua bindings for Ipelib. If installed properly, it can be loaded dynamically from Lua using require. It is also used by ipescript.
  • libipecanvas implements the Ipe canvas module. It provides a widget for displaying and editing Ipe objects.
  • libipeui implements Lua bindings for user interfaces. This library does not depend on any other Ipe component, and can be used for other Lua projects.

Here is an annotated list of the modules:

Finally, here is list of the pages describing Lua bindings:


ipe-7.1.4/build/doc/classipe_1_1_object.html0000644000175000017500000016203212120621776020505 0ustar otfriedotfried Ipelib: ipe::Object Class Reference

#include <ipeobject.h>

Inherited by ipe::Group, ipe::Image, ipe::Path, ipe::Reference, and ipe::Text.

Public Types

enum  Type {
  EGroup, EPath, EText, EImage,
  EReference
}

Public Member Functions

virtual ~Object ()=0
virtual void accept (Visitor &visitor) const =0
virtual Objectclone () const =0
virtual GroupasGroup ()
virtual TextasText ()
virtual PathasPath ()
virtual ImageasImage ()
virtual ReferenceasReference ()
virtual Type type () const =0
virtual TPinned pinned () const
void setPinned (TPinned pin)
TTransformations transformations () const
void setTransformations (TTransformations trans)
void setMatrix (const Matrix &matrix)
const Matrixmatrix () const
virtual bool setAttribute (Property prop, Attribute value, Attribute stroke, Attribute fill)
virtual Attribute getAttribute (Property prop)
virtual void saveAsXml (Stream &stream, String layer) const =0
virtual void draw (Painter &painter) const =0
virtual void drawSimple (Painter &painter) const =0
virtual double distance (const Vector &v, const Matrix &m, double bound) const =0
virtual void addToBBox (Rect &box, const Matrix &m, bool cp) const =0
virtual void snapVtx (const Vector &mouse, const Matrix &m, Vector &pos, double &bound) const =0
virtual void checkStyle (const Cascade *sheet, AttributeSeq &seq) const
virtual void snapBnd (const Vector &mouse, const Matrix &m, Vector &pos, double &bound) const

Protected Member Functions

 Object ()
 Object (const AllAttributes &attr)
 Object (const Object &rhs)
 Object (const XmlAttributes &attr)
void saveAttributesAsXml (Stream &stream, String layer) const

Static Protected Member Functions

static void checkSymbol (Kind kind, Attribute attr, const Cascade *sheet, AttributeSeq &seq)

Protected Attributes

Matrix iMatrix
TPinned iPinned: 8
TTransformations iTransformations: 8

Detailed Description

Base class for all Ipe objects, composite or leaf.

All objects are derived from this class. It provides functionality common to all objects, and carries the standard attributes.

All Object's provide a constant time copy constructor (and a virtual Object::clone() method). Objects of non-constant size realize this by separating the implementation and using reference counting. In particular, copying a composite object does not create new copies of the components.

Object has only three attributes: the transformation matrix, the pinning status, and the allowed transformations.

If an object is pinned, it cannot be moved at all (or only in the non-pinned direction) from the Ipe user interface.

Restricting the allowed transformations works somewhat differently: It doesn't stop transformations being applied to the object, but they only effect the position of the reference point (the origin of the object coordinate system), and (if transformations() == ETransformationsRigidMotions) the orientation of the object coordinate system.

Member Enumeration Documentation

Enumerator:
EGroup 
EPath 
EText 
EImage 
EReference 

Constructor & Destructor Documentation

Object::~Object ( )
pure virtual

Pure virtual destructor.

Object::Object ( )
explicitprotected

Create object with identity matrix, no pinning, all transformations.

Object::Object ( const AllAttributes attr)
explicitprotected

Create object by taking pinning/transforming from attr and setting identity matrix.

Object::Object ( const Object rhs)
protected

Copy constructor.

Object::Object ( const XmlAttributes attr)
explicitprotected

Construct from XML stream.

Member Function Documentation

virtual void ipe::Object::accept ( Visitor visitor) const
pure virtual

Calls visitXXX method of the visitor.

Implemented in ipe::Path, ipe::Group, ipe::Text, ipe::Reference, and ipe::Image.

virtual Object* ipe::Object::clone ( ) const
pure virtual

Make a copy of this object (constant-time).

Implemented in ipe::Group, ipe::Reference, ipe::Text, ipe::Path, and ipe::Image.

Group * Object::asGroup ( )
virtual

Return pointer to this object if it is an Group, 0 otherwise.

Reimplemented in ipe::Group.

Text * Object::asText ( )
virtual

Return pointer to this object if it is an Text, 0 otherwise.

Reimplemented in ipe::Text.

Path * Object::asPath ( )
virtual

Return pointer to this object if it is an Path, 0 otherwise.

Reimplemented in ipe::Path.

Image * Object::asImage ( )
virtual

Return pointer to this object if it is an Image , 0 otherwise.

Reimplemented in ipe::Image.

Reference * Object::asReference ( )
virtual

Return pointer to this object if it is an Ref, 0 otherwise.

Reimplemented in ipe::Reference.

virtual Type ipe::Object::type ( ) const
pure virtual
TPinned Object::pinned ( ) const
virtual

Return pinning mode of the object.

Reimplemented in ipe::Group.

void Object::setPinned ( TPinned  pin)

Set pinning mode of the object.

TTransformations ipe::Object::transformations ( ) const
inline

Return allowed transformations of the object.

void Object::setTransformations ( TTransformations  trans)

Set allowed transformations of the object.

void Object::setMatrix ( const Matrix matrix)

Set the transformation matrix.

Don't use this on an Object in a Page, because it wouldn't invalidate its bounding box. Call Page::transform instead.

const Matrix& ipe::Object::matrix ( ) const
inline

Return transformation matrix.

bool Object::setAttribute ( Property  prop,
Attribute  value,
Attribute  stroke,
Attribute  fill 
)
virtual

Set an attribute on this object.

Returns true if an attribute was actually changed. The arguments stroke and fill are only used then prop is EPropPathMode, and stroking or filling is added to an object that didn't have it before.

Reimplemented in ipe::Path, ipe::Group, ipe::Reference, and ipe::Text.

Attribute Object::getAttribute ( Property  prop)
virtual

Get setting of an attribute of this object.

If object does not have this attribute, returnes "undefined" attribute.

Reimplemented in ipe::Path, ipe::Reference, and ipe::Text.

virtual void ipe::Object::saveAsXml ( Stream stream,
String  layer 
) const
pure virtual

Save the object in XML format.

Implemented in ipe::Path, ipe::Group, ipe::Reference, ipe::Text, and ipe::Image.

virtual void ipe::Object::draw ( Painter painter) const
pure virtual

Draw the object.

Implemented in ipe::Path, ipe::Group, ipe::Reference, ipe::Text, and ipe::Image.

virtual void ipe::Object::drawSimple ( Painter painter) const
pure virtual

Draw simple version for selecting and transforming.

Implemented in ipe::Path, ipe::Group, ipe::Reference, ipe::Text, and ipe::Image.

virtual double ipe::Object::distance ( const Vector v,
const Matrix m,
double  bound 
) const
pure virtual

Return distance of transformed object to point v. If larger than bound, can just return bound.

Implemented in ipe::Path, ipe::Group, ipe::Text, ipe::Reference, and ipe::Image.

virtual void ipe::Object::addToBBox ( Rect box,
const Matrix m,
bool  cp 
) const
pure virtual

Extend box to include the object transformed by m.

For objects in a page, don't call this directly. The Page caches the bounding box of each object, so it is far more efficient to call Page::bbox.

Control points that lie outside the visual object are included if cp is true.

If called with an empty box and cp == false, the result of this function is a tight bounding box for the object, with a little leeway in case the boundary is determined by a spline (it has to be approximated to perform this operation).

Implemented in ipe::Path, ipe::Group, ipe::Text, ipe::Reference, and ipe::Image.

virtual void ipe::Object::snapVtx ( const Vector mouse,
const Matrix m,
Vector pos,
double &  bound 
) const
pure virtual

Compute possible vertex snapping position for transformed object.

Looks only for positions closer than bound. If successful, modify pos and bound.

Implemented in ipe::Path, ipe::Group, ipe::Text, ipe::Reference, and ipe::Image.

void Object::checkStyle ( const Cascade sheet,
AttributeSeq seq 
) const
virtual

Check all symbolic attributes.

Reimplemented in ipe::Path, ipe::Group, ipe::Reference, and ipe::Text.

void Object::snapBnd ( const Vector mouse,
const Matrix m,
Vector pos,
double &  bound 
) const
virtual

Compute boundary snapping position for transformed object.

Looks only for positions closer than bound. If successful, modify pos and bound. The default implementation does nothing.

Reimplemented in ipe::Path, ipe::Group, and ipe::Reference.

void Object::saveAttributesAsXml ( Stream stream,
String  layer 
) const
protected

Write layer, pin, transformations, matrix to XML stream.

void Object::checkSymbol ( Kind  kind,
Attribute  attr,
const Cascade sheet,
AttributeSeq seq 
)
staticprotected

Check whether attribute is either absolute or defined in the style sheet cascade sheet. Add attr to seq if this is not the case.

Member Data Documentation

Matrix ipe::Object::iMatrix
protected
TPinned ipe::Object::iPinned
protected
TTransformations ipe::Object::iTransformations
protected

The documentation for this class was generated from the following files:
  • ipeobject.h
  • ipeobject.cpp

ipe-7.1.4/build/doc/classipe_1_1_document-members.html0000644000175000017500000004551112120621776022507 0ustar otfriedotfried Ipelib: Member List
ipe::Document Member List

This is the complete list of members for ipe::Document, including all inherited members.

cascade()ipe::Documentinline
cascade() const ipe::Documentinline
checkStyle(AttributeSeq &seq) const ipe::Document
countPages() const ipe::Documentinline
countTotalViews() const ipe::Document
Document()ipe::Document
Document(const Document &rhs)ipe::Document
EEps enum valueipe::Document
EExport enum valueipe::Document
EFileOpenError enum valueipe::Document
EIpe5 enum valueipe::Document
EMarkedView enum valueipe::Document
ENoColor enum valueipe::Document
ENoZip enum valueipe::Document
EPdf enum valueipe::Document
ErrLatex enum valueipe::Document
ErrLatexOutput enum valueipe::Document
ErrNoDir enum valueipe::Document
ErrNoIconv enum valueipe::Document
ErrNone enum valueipe::Document
ErrNoText enum valueipe::Document
ErrOldPdfLatex enum valueipe::Document
ErrRunLatex enum valueipe::Document
ErrWritingSource enum valueipe::Document
ESaveNormal enum valueipe::Document
EUnknown enum valueipe::Document
EVersionTooOld enum valueipe::Document
EVersionTooRecent enum valueipe::Document
EXml enum valueipe::Document
exportPages(const char *fname, uint flags, int fromPage, int toPage) const ipe::Document
exportView(const char *fname, TFormat format, uint flags, int pno, int vno) const ipe::Document
fileFormat(DataSource &source)ipe::Documentstatic
findBitmaps(BitmapFinder &bm) const ipe::Document
fontPool() const ipe::Documentinline
formatFromFilename(String fn)ipe::Documentstatic
hasGradients() const ipe::Document
hasTilings() const ipe::Document
hasTransparency() const ipe::Document
hasTrueTypeFonts() const ipe::Document
insert(int no, Page *page)ipe::Document
load(DataSource &source, TFormat format, int &reason)ipe::Documentstatic
load(const char *fname, int &reason)ipe::Documentstatic
LoadErrors enum nameipe::Document
loadWithErrorReport(const char *fname)ipe::Documentstatic
page(int no) const ipe::Documentinline
page(int no)ipe::Documentinline
properties() const ipe::Documentinline
push_back(Page *page)ipe::Document
remove(int no)ipe::Document
replaceCascade(Cascade *cascade)ipe::Document
runLatex(String &logFile)ipe::Document
runLatex()ipe::Document
save(TellStream &stream, TFormat format, uint flags) const ipe::Document
save(const char *fname, TFormat format, uint flags) const ipe::Document
saveAsXml(Stream &stream, bool usePdfBitmaps=false) const ipe::Document
set(int no, Page *page)ipe::Document
setFontPool(FontPool *fontPool)ipe::Document
setProperties(const SProperties &info)ipe::Document
TFormat enum nameipe::Document
~Document()ipe::Document

ipe-7.1.4/build/doc/functions_func_0x64.html0000644000175000017500000004356612120621776020532 0ustar otfriedotfried Ipelib: Class Members - Functions
 

- d -


ipe-7.1.4/build/doc/classipe_1_1_closed_spline.html0000644000175000017500000005163712120621776022072 0ustar otfriedotfried Ipelib: ipe::ClosedSpline Class Reference

#include <ipeshape.h>

Inherits ipe::SubPath.

Public Member Functions

 ClosedSpline (const std::vector< Vector > &v)
virtual Type type () const
virtual const ClosedSplineasClosedSpline () const
void beziers (std::vector< Bezier > &bez) const
virtual void save (Stream &stream) const
virtual void draw (Painter &painter) const
virtual void addToBBox (Rect &box, const Matrix &m, bool cp) const
virtual double distance (const Vector &v, const Matrix &m, double bound) const
virtual void snapVtx (const Vector &mouse, const Matrix &m, Vector &pos, double &bound) const
virtual void snapBnd (const Vector &mouse, const Matrix &m, Vector &pos, double &bound) const
- Public Member Functions inherited from ipe::SubPath
virtual ~SubPath ()=0
virtual bool closed () const
virtual const EllipseasEllipse () const
virtual const CurveasCurve () const

Public Attributes

std::vector< VectoriCP

Additional Inherited Members

- Public Types inherited from ipe::SubPath
enum  Type { ECurve, EEllipse, EClosedSpline }

Detailed Description

A closed B-spline curve.

Constructor & Destructor Documentation

ClosedSpline::ClosedSpline ( const std::vector< Vector > &  v)

Member Function Documentation

SubPath::Type ClosedSpline::type ( ) const
virtual

Return type of this subpath.

Implements ipe::SubPath.

const ClosedSpline * ClosedSpline::asClosedSpline ( ) const
virtual

Return this object as an ClosedSpline, or 0 if it's not a closed spline.

Reimplemented from ipe::SubPath.

void ClosedSpline::beziers ( std::vector< Bezier > &  bez) const
void ClosedSpline::save ( Stream stream) const
virtual

Save subpath to XML stream.

Implements ipe::SubPath.

void ClosedSpline::draw ( Painter painter) const
virtual

Draw subpath (does not call drawPath()).

Implements ipe::SubPath.

void ClosedSpline::addToBBox ( Rect box,
const Matrix m,
bool  cp 
) const
virtual

Add subpath to box.

Implements ipe::SubPath.

double ClosedSpline::distance ( const Vector v,
const Matrix m,
double  bound 
) const
virtual

Return distance from v to subpath transformed by m.

Implements ipe::SubPath.

void ClosedSpline::snapVtx ( const Vector mouse,
const Matrix m,
Vector pos,
double &  bound 
) const
virtual

Snap to vertex.

Implements ipe::SubPath.

void ClosedSpline::snapBnd ( const Vector mouse,
const Matrix m,
Vector pos,
double &  bound 
) const
virtual

Snap to boundary of subpath.

Implements ipe::SubPath.

Member Data Documentation

std::vector<Vector> ipe::ClosedSpline::iCP

The documentation for this class was generated from the following files:
  • ipeshape.h
  • ipeshape.cpp

ipe-7.1.4/build/doc/classipe_1_1_repository-members.html0000644000175000017500000000637712120621776023117 0ustar otfriedotfried Ipelib: Member List
ipe::Repository Member List

This is the complete list of members for ipe::Repository, including all inherited members.

cleanup()ipe::Repositorystatic
get()ipe::Repositorystatic
toIndex(String str)ipe::Repository
toString(int index) const ipe::Repository

ipe-7.1.4/build/doc/classipe_1_1_reference.html0000644000175000017500000016137012120621776021201 0ustar otfriedotfried Ipelib: ipe::Reference Class Reference

#include <ipereference.h>

Inherits ipe::Object.

Public Types

enum  {
  EHasStroke = 0x001, EHasFill = 0x002, EHasPen = 0x004, EHasSize = 0x008,
  EIsMark = 0x010, EIsArrow = 0x020
}
- Public Types inherited from ipe::Object
enum  Type {
  EGroup, EPath, EText, EImage,
  EReference
}

Public Member Functions

 Reference (const AllAttributes &attr, Attribute name, Vector pos)
 Reference (const XmlAttributes &attr, String data)
virtual Objectclone () const
virtual ReferenceasReference ()
virtual Type type () const
virtual void accept (Visitor &visitor) const
virtual void saveAsXml (Stream &stream, String layer) const
virtual void draw (Painter &painter) const
virtual void drawSimple (Painter &painter) const
virtual void addToBBox (Rect &box, const Matrix &m, bool cp) const
virtual double distance (const Vector &v, const Matrix &m, double bound) const
virtual void snapVtx (const Vector &mouse, const Matrix &m, Vector &pos, double &bound) const
virtual void snapBnd (const Vector &mouse, const Matrix &m, Vector &pos, double &bound) const
virtual void checkStyle (const Cascade *sheet, AttributeSeq &seq) const
void setName (Attribute name)
Attribute name () const
void setStroke (Attribute color)
Attribute stroke () const
void setFill (Attribute color)
Attribute fill () const
Attribute pen () const
void setPen (Attribute pen)
void setSize (Attribute size)
Attribute size () const
Vector position () const
virtual bool setAttribute (Property prop, Attribute value, Attribute stroke, Attribute fill)
virtual Attribute getAttribute (Property prop)
uint flags () const
- Public Member Functions inherited from ipe::Object
virtual ~Object ()=0
virtual GroupasGroup ()
virtual TextasText ()
virtual PathasPath ()
virtual ImageasImage ()
virtual TPinned pinned () const
void setPinned (TPinned pin)
TTransformations transformations () const
void setTransformations (TTransformations trans)
void setMatrix (const Matrix &matrix)
const Matrixmatrix () const

Static Public Member Functions

static uint flagsFromName (String name)

Additional Inherited Members

- Protected Member Functions inherited from ipe::Object
 Object ()
 Object (const AllAttributes &attr)
 Object (const Object &rhs)
 Object (const XmlAttributes &attr)
void saveAttributesAsXml (Stream &stream, String layer) const
- Static Protected Member Functions inherited from ipe::Object
static void checkSymbol (Kind kind, Attribute attr, const Cascade *sheet, AttributeSeq &seq)
- Protected Attributes inherited from ipe::Object
Matrix iMatrix
TPinned iPinned: 8
TTransformations iTransformations: 8

Detailed Description

The reference object.

A Reference uses a symbol, that is, an object defined in an Ipe StyleSheet. The object is defined as a named symbol in the style sheet, and can be reused arbitrarily often in the document. This can, for instance, be used for backgrounds on multi-page documents.

It is admissible to refer to an undefined object (that is, the current style sheet cascade does not define a symbol with the given name). Nothing will be drawn in this case.

The Reference has a stroke, fill, and pen attribute. When drawing a symbol, these attributes are made available to the symbol through the names "sym-stroke", "sym-fill", and "sym-pen". These are not defined by the style sheet, but resolved by the Painter when the symbol sets its attributes.

Note that it is not possible to determine whether a symbol is filled from the Reference object.

The size attribute is of type ESymbolSize, and indicates a magnification factor applied to the symbol. This magnification is applied after the untransformation indicated in the Reference and in the Symbol has been performed, so that symbols are magnified even if they specify ETransformationsTranslations.

The size is meant for symbols such as marks, that can be shown in different sizes. Another application of symbols is for backgrounds and logos. Their size should not be changed when the user changes the symbolsize for the entire page. For such symbols, the size attribute of the Reference should be set to the absolute value zero. This means that no magnification is applied to the object, and it also stops setAttribute() from modifying the size. (The size can still be changed using setSize(), but this is not available from Lua.)

Member Enumeration Documentation

anonymous enum
Enumerator:
EHasStroke 
EHasFill 
EHasPen 
EHasSize 
EIsMark 
EIsArrow 

Constructor & Destructor Documentation

Reference::Reference ( const AllAttributes attr,
Attribute  name,
Vector  pos 
)
explicit

Create a reference to the named object in stylesheet.

Reference::Reference ( const XmlAttributes attr,
String  data 
)
explicit

Create from XML stream.

Member Function Documentation

Object * Reference::clone ( ) const
virtual

Clone object.

Implements ipe::Object.

Reference * Reference::asReference ( )
virtual

Return pointer to this object.

Reimplemented from ipe::Object.

Object::Type Reference::type ( ) const
virtual

Implements ipe::Object.

void Reference::accept ( Visitor visitor) const
virtual

Call visitReference of visitor.

Implements ipe::Object.

void Reference::saveAsXml ( Stream stream,
String  layer 
) const
virtual

Save in XML format.

Implements ipe::Object.

void Reference::draw ( Painter painter) const
virtual

Draw reference.

If the symbolic attribute is not defined in the current style sheet, nothing is drawn at all.

Implements ipe::Object.

void Reference::drawSimple ( Painter painter) const
virtual

Draw simple version for selecting and transforming.

Implements ipe::Object.

void Reference::addToBBox ( Rect box,
const Matrix m,
bool  cp 
) const
virtual

Extend box to include the object transformed by m.

For objects in a page, don't call this directly. The Page caches the bounding box of each object, so it is far more efficient to call Page::bbox.Control points that lie outside the visual object are included if cp is true.If called with an empty box and cp == false, the result of this function is a tight bounding box for the object, with a little leeway in case the boundary is determined by a spline (it has to be approximated to perform this operation).

This only adds the position to the box.

Implements ipe::Object.

double Reference::distance ( const Vector v,
const Matrix m,
double  bound 
) const
virtual

Return distance of transformed object to point v. If larger than bound, can just return bound.

Implements ipe::Object.

void Reference::snapVtx ( const Vector mouse,
const Matrix m,
Vector pos,
double &  bound 
) const
virtual

Compute possible vertex snapping position for transformed object.

Looks only for positions closer than bound. If successful, modify pos and bound.

Implements ipe::Object.

void Reference::snapBnd ( const Vector mouse,
const Matrix m,
Vector pos,
double &  bound 
) const
virtual

Compute boundary snapping position for transformed object.

Looks only for positions closer than bound. If successful, modify pos and bound. The default implementation does nothing.

Reimplemented from ipe::Object.

void Reference::checkStyle ( const Cascade sheet,
AttributeSeq seq 
) const
virtual

Check all symbolic attributes.

Reimplemented from ipe::Object.

void Reference::setName ( Attribute  name)

Set name of symbol referenced.

Attribute ipe::Reference::name ( ) const
inline

Return symbolic name.

void Reference::setStroke ( Attribute  color)

Set stroke color.

Attribute ipe::Reference::stroke ( ) const
inline

Return stroke color.

void Reference::setFill ( Attribute  color)

Set fill color.

Attribute ipe::Reference::fill ( ) const
inline

Return fill color.

Attribute ipe::Reference::pen ( ) const
inline

Return pen.

void Reference::setPen ( Attribute  pen)

Set pen.

void Reference::setSize ( Attribute  size)

Set size (magnification) of symbol.

Attribute ipe::Reference::size ( ) const
inline

Return symbol size.

Vector ipe::Reference::position ( ) const
inline

Return position of symbol on page.

bool Reference::setAttribute ( Property  prop,
Attribute  value,
Attribute  nStroke,
Attribute  nFill 
)
virtual

Set an attribute on this object.

Returns true if an attribute was actually changed. The arguments stroke and fill are only used then prop is EPropPathMode, and stroking or filling is added to an object that didn't have it before.

Reimplemented from ipe::Object.

Attribute Reference::getAttribute ( Property  prop)
virtual

Get setting of an attribute of this object.

If object does not have this attribute, returnes "undefined" attribute.

Reimplemented from ipe::Object.

uint ipe::Reference::flags ( ) const
inline
uint Reference::flagsFromName ( String  name)
static

The documentation for this class was generated from the following files:
  • ipereference.h
  • ipereference.cpp

ipe-7.1.4/build/doc/classipe_1_1_base64_source.html0000644000175000017500000001251312120621776021701 0ustar otfriedotfried Ipelib: ipe::Base64Source Class Reference
ipe::Base64Source Class Reference

#include <ipeutils.h>

Inherits ipe::DataSource.

Public Member Functions

 Base64Source (DataSource &source)
virtual int getChar ()
- Public Member Functions inherited from ipe::DataSource
virtual ~DataSource ()=0

Detailed Description

Filter source adding Base64 decoding.

Constructor & Destructor Documentation

Base64Source::Base64Source ( DataSource source)

Member Function Documentation

int Base64Source::getChar ( )
virtual

Get one more character, or EOF.

Implements ipe::DataSource.


The documentation for this class was generated from the following files:
  • ipeutils.h
  • ipeutils.cpp

ipe-7.1.4/build/doc/classipe_1_1_fonts.html0000644000175000017500000001722212120621776020370 0ustar otfriedotfried Ipelib: ipe::Fonts Class Reference

#include <ipefonts.h>

Public Member Functions

 ~Fonts ()
FacegetFace (int id)

Static Public Member Functions

static FontsNew (const FontPool *fontPool)
static cairo_font_face_t * screenFont ()
static String freetypeVersion ()

Detailed Description

Provides the fonts used to render text.

Constructor & Destructor Documentation

Fonts::~Fonts ( )

Delete all the loaded Faces.

Member Function Documentation

Fonts * Fonts::New ( const FontPool *  fontPool)
static
Face * Fonts::getFace ( int  id)

Get a typeface.

Corresponds to a Freetype "face", or a PDF font resource. A Face can be loaded at various sizes (transformations), resulting in individual FaceSize's.

cairo_font_face_t * Fonts::screenFont ( )
static

Return a Cairo font to render to the screen w/o Latex font.

String Fonts::freetypeVersion ( )
static

The documentation for this class was generated from the following files:
  • ipefonts.h
  • ipefonts.cpp

ipe-7.1.4/build/doc/classipe_1_1_document.html0000644000175000017500000014700612120621776021061 0ustar otfriedotfried Ipelib: ipe::Document Class Reference

#include <ipedoc.h>

Classes

struct  SProperties
 Properties of a document. More...

Public Types

enum  TFormat {
  EXml, EPdf, EEps, EIpe5,
  EUnknown
}
enum  {
  ESaveNormal = 0, EExport = 1, ENoZip = 2, EMarkedView = 4,
  ENoColor = 8
}
enum  LoadErrors { EVersionTooOld = -1, EVersionTooRecent = -2, EFileOpenError = -3 }
enum  {
  ErrNone, ErrNoText, ErrNoDir, ErrWritingSource,
  ErrOldPdfLatex, ErrRunLatex, ErrLatex, ErrLatexOutput,
  ErrNoIconv
}

Public Member Functions

 Document ()
 Document (const Document &rhs)
 ~Document ()
bool save (TellStream &stream, TFormat format, uint flags) const
bool save (const char *fname, TFormat format, uint flags) const
bool exportPages (const char *fname, uint flags, int fromPage, int toPage) const
bool exportView (const char *fname, TFormat format, uint flags, int pno, int vno) const
void saveAsXml (Stream &stream, bool usePdfBitmaps=false) const
int countPages () const
int countTotalViews () const
const Pagepage (int no) const
Pagepage (int no)
Pageset (int no, Page *page)
void insert (int no, Page *page)
void push_back (Page *page)
Pageremove (int no)
SProperties properties () const
void setProperties (const SProperties &info)
Cascadecascade ()
const Cascadecascade () const
CascadereplaceCascade (Cascade *cascade)
void setFontPool (FontPool *fontPool)
const FontPool * fontPool () const
bool hasTrueTypeFonts () const
bool hasTransparency () const
bool hasTilings () const
bool hasGradients () const
void findBitmaps (BitmapFinder &bm) const
bool checkStyle (AttributeSeq &seq) const
int runLatex (String &logFile)
int runLatex ()

Static Public Member Functions

static TFormat fileFormat (DataSource &source)
static TFormat formatFromFilename (String fn)
static Documentload (DataSource &source, TFormat format, int &reason)
static Documentload (const char *fname, int &reason)
static DocumentloadWithErrorReport (const char *fname)

Detailed Description

The model for an Ipe document.

The Document class represents the contents of an Ipe document, and all the methods necessary to load, save, and modify it.

Member Enumeration Documentation

There are several Ipe document save formats.

Enumerator:
EXml 

Save as XML.

EPdf 

Save as PDF.

EEps 

Save as Encapsulated Postscript.

EIpe5 

Ancient Ipe format.

EUnknown 

Unknown file format.

anonymous enum

Options for saving Ipe documents (to PDF and Postscript)

Enumerator:
ESaveNormal 

Nothing special.

EExport 

Don't include Ipe markup.

ENoZip 

Do not compress streams.

EMarkedView 

Create marked views only.

ENoColor 

No color commands in EPS output.

Errors that can happen while loading documents.

Enumerator:
EVersionTooOld 

The version of the file is too old.

EVersionTooRecent 

The file version is newer than this Ipelib.

EFileOpenError 

Error opening the file.

anonymous enum

Error codes returned by RunLatex.

Enumerator:
ErrNone 
ErrNoText 
ErrNoDir 
ErrWritingSource 
ErrOldPdfLatex 
ErrRunLatex 
ErrLatex 
ErrLatexOutput 
ErrNoIconv 

Constructor & Destructor Documentation

Document::Document ( )

Construct an empty document for filling by a client.

As constructed, it has no pages, A4 media, and only the standard style sheet.

Document::Document ( const Document rhs)

Copy constructor.

Document::~Document ( )

Destructor.

Member Function Documentation

Document::TFormat Document::fileFormat ( DataSource source)
static

Determine format of file in source.

Document::TFormat Document::formatFromFilename ( String  fn)
static

Determine format of file from filename fn.

Document * Document::load ( DataSource source,
TFormat  format,
int &  reason 
)
static

Construct a document from an input stream.

Returns 0 if the stream couldn't be parsed, and a reason explaining that in reason. If reason is positive, it is a file (stream) offset where parsing failed. If reason is negative, it is an error code, see Document::LoadErrors.

Document * Document::load ( const char *  fname,
int &  reason 
)
static
Document * Document::loadWithErrorReport ( const char *  fname)
static
bool Document::save ( TellStream stream,
TFormat  format,
uint  flags 
) const

Save in a stream.

Returns true if sucessful.

bool Document::save ( const char *  fname,
TFormat  format,
uint  flags 
) const
bool Document::exportPages ( const char *  fname,
uint  flags,
int  fromPage,
int  toPage 
) const

Export a range of pages to PDF.

bool Document::exportView ( const char *  fname,
TFormat  format,
uint  flags,
int  pno,
int  vno 
) const

Export a single view to PDF or EPS.

void Document::saveAsXml ( Stream stream,
bool  usePdfBitmaps = false 
) const

Save in XML format into an Stream.

int ipe::Document::countPages ( ) const
inline

Return number of pages of document.

int Document::countTotalViews ( ) const

Return total number of views in all pages.

const Page* ipe::Document::page ( int  no) const
inline

Return page (const version).

The first page is no 0.

Page* ipe::Document::page ( int  no)
inline

Return page.

The first page is no 0.

Page * Document::set ( int  no,
Page page 
)

Replace page.

Returns the original page.

void Document::insert ( int  no,
Page page 
)

Insert a new page.

The page is inserted at index no.

void Document::push_back ( Page page)

Append a new page.

Page * Document::remove ( int  no)

Remove a page.

Returns the page that has been removed.

SProperties ipe::Document::properties ( ) const
inline

Return document properties.

void Document::setProperties ( const SProperties info)

Set document properties.

Cascade* ipe::Document::cascade ( )
inline

Return stylesheet cascade.

const Cascade* ipe::Document::cascade ( ) const
inline

Return stylesheet cascade (const version).

Cascade * Document::replaceCascade ( Cascade sheets)

Replace the entire style sheet cascade.

Takes ownership of cascade, and returns the original cascade.

void Document::setFontPool ( FontPool *  fontPool)

Update the font pool (after running Pdflatex).

Takes ownership of the font pool.

const FontPool* ipe::Document::fontPool ( ) const
inline

Return the current FontPool.

bool Document::hasTrueTypeFonts ( ) const

Return whether this document uses any Truetype fonts.

bool Document::hasTransparency ( ) const

Does this document make any use of transparency?

The document is considered to make use of transparency if its style sheets define any opacities whose value is not 1.0.

bool Document::hasTilings ( ) const

Does this document contain any tiling patterns?

bool Document::hasGradients ( ) const

Does this document contain any gradients?

void Document::findBitmaps ( BitmapFinder bm) const

Create a list of all bitmaps in the document.

bool Document::checkStyle ( AttributeSeq seq) const

Check all symbolic attributes in the document.

This function verifies that all symbolic attributes in the document are defined in the style sheet. It appends to seq all symbolic attributes (in no particular order, but without duplicates) that are NOT defined.

Returns true if there are no undefined symbolic attributes in the document.

int Document::runLatex ( String logFile)

Run PdfLatex.

int Document::runLatex ( )

Run Pdflatex (suitable for console applications)

Success/error is reported on stderr.


The documentation for this class was generated from the following files:
  • ipedoc.h
  • ipedoc.cpp

ipe-7.1.4/build/doc/classipe_1_1_buffer_source.html0000644000175000017500000001247612120621776022076 0ustar otfriedotfried Ipelib: ipe::BufferSource Class Reference
ipe::BufferSource Class Reference

#include <ipebase.h>

Inherits ipe::DataSource.

Public Member Functions

 BufferSource (const Buffer &buffer)
virtual int getChar ()
- Public Member Functions inherited from ipe::DataSource
virtual ~DataSource ()=0

Detailed Description

Data source for parsing from a buffer.

Constructor & Destructor Documentation

BufferSource::BufferSource ( const Buffer buffer)

Member Function Documentation

int BufferSource::getChar ( )
virtual

Get one more character, or EOF.

Implements ipe::DataSource.


The documentation for this class was generated from the following files:
  • ipebase.h
  • ipebase.cpp

ipe-7.1.4/build/doc/functions_0x77.html0000644000175000017500000001415412120621776017512 0ustar otfriedotfried Ipelib: Class Members
Here is a list of all class members with links to the classes they belong to:

- w -


ipe-7.1.4/build/doc/ftv2doc.png0000644000175000017500000000135212120621776016100 0ustar otfriedotfried‰PNG  IHDRÚ}\ˆ±IDATxíMOS[…Ÿžsúa?-XZ(PD4‚ AWbu`b 77wäHFÆCËÔÂÿà/`vo„ˆAPòq‹P @ ­ûÝè980 îà¤+»§Ýy×^ïZï9SW¹\83g‰3'°Nâçl¹¸_b¯p ïåûÆVÜÖ¡€Ÿ×"¬Ö†X€d]Ðà3“ÉÃÄÌ™xŸ ßMàœ[<çSPkvc—hÈ'…™˜^Åm™hØ7 `Û™¦ èÀåráq›‘œ¾!daeKŸþÆÕ˜:Ì*³_דâèi?I–eP*B7Ÿ¿åô!¹Ýgr6Ër6oKbëþãðôrI”ËTˆüªŒ¨xóö=›ù¢&‰(e+ßóÄkýÇ`ëÁÜb.“¸ÐW×w0¥°jÑzN™¬|©WEãµ¢a¯6[öX†AkÓù*/œ¨‰€ÉY­ ÿV’§–u²jÂ>1W *½·°PGŽzÿ¨/Eg{ ŸÇâaoŠÁVú:è¿™¤1$ôR§W,–ªà¨@ŠË56¾ÀÔÜ-¾,mê¸Î/æè¹– òr5¥T*S(Vf8ö9u’ Õ£w›ùóa=Í<{Ò¡UŒ÷r¯+ÉådDÏF$è°…£é¿`zþ»ÎúöN‘µÜ®0Q3£~_^Ëóâ¯N=ˆvpTà±LžT}ˆîkq†Òm<¼ÎÓ?Zh¿X£ï_þÝ¥[)ƒ `gêÃa_Ô*äÔ2`'=õ´Fÿ2EâÁPú ÷»›l=8‹Wv°%THqÉ¿<"¤ïG¾ÆxH{#ÆÖ«aÔJÕÞ‡—m‹„ çñKsÿàñVŠØ¡°·MâÒ^ TÁ– Ý›r¥ß½ømüÿ_™?ªWİ÷#uIEND®B`‚ipe-7.1.4/build/doc/manual.pdf0000644000175000017500000146644212120621776016013 0ustar otfriedotfried%PDF-1.5 %ÐÔÅØ 2 0 obj << /Type /ObjStm /N 100 /First 806 /Length 1198 /Filter /FlateDecode >> stream xÚ•VMoÜ6½ï¯˜Þ MÄ‘`pÓ""Fí4Eo\-×V£Jrâüú¾ÑJέW냭‘È÷fæÍp¸‚2ÊIedÈ *Hd$LEBã¡IGÂ’ÌðÅ‘”’¤ ™Û[ŽMRÂ4¤tN² å2æÔi7MÚYR–r€”£¦”[¹Ò’L†·œ LmÈäx+È’òŒ,BÊYÆj²XDzuXsä2D.È©le$9¦ÈÉÁ»1ä ¼T(¦ kVQ5«©(¯E¦J€ OmÉqæN®À,²v9žOƒgÚ‚eä‘™1žH¡€@Òà;ø$|àS¬K©t±ÓA¡%ð€ ­Ø! Œ ‹®-»mž¾aH^qžs`λÅW#ÜJ@Ka »@ „a~1–÷€Ùf ˜­d_­Qêå$Ž×Qá4þ!áœZ!L…â0Á\ 7& ¥‘™äè2LˆòÈŒóFäJ$ÇŒ"IaÇxÑ9™Y!^n!î*ôŠÌÇÀap9P.©„äÀa(6À¬,`V,9öI=¦fsà`ÖÔ@å䨴–£b¨ú”³³a!Q=iTÁÉÁ°l€™{ YÂ`‰´&¾J[ØÕÙ½¹¢7ïâu¤7¿Ò‹.”}›×â%Ÿ¯^|uwúHým Ï±Ù„´jX©ÞPÜÒû6üôòI¹§¹Xǡ筴­êÐ=½_í÷¿ MH¾¦·±)CÛÿ`X?`æ`?&Ç1Åõ?X[BM±]#¯rH)4=u¡Þ//@§0wUsC¾ÙPWúšíÓ\ë=þªOñKñÐ¥¦2Ö1-aó=ö24¯hã»[êúû:¼"ŸRüÚ½Ùúj ¦õ}R³Äh&!’oºÖCˆò~a§øïwëXWåèÓ¯»X=ÒéûT­a-ùu{–¿cÜ ­_Ò½˜Ú#Å¡]lŠl¿ùƒ¿‹¢ 1Wtèu·1õåÐiÔ©‚ÇrSß.d«ç&½ôýíI]¢4|ëODL}ù~ço‰} 鉩ÿÛÀÍòàiÆž8¢Ü„¾j|Û¢IúÊgÕÞ¥ Ô§A&Ù0;zVîDÔ$ÝEs3Ô>ŠšÔ{WÉyþ𨜠h7 ½‘ÏšüöÍïÚ£óÑ̃G¾» áX‹N‡ô2…³Íó·ãq؇=€ìÇË“¾Ñ“ðVáëÒÖIí_bü²óéËÒö‡&õ›ŠçôIƒÍβò½3µ%áxcØ&Lœþø±šH¦u±¹óètLÖØVåq¿n–ñêÖ'h¶USU ¯†À}Ò¼Ëa‡Äx'?'Ѐ·jq]õKÁ¨yºÇaÍ…Œqs~ð×á¯ŸËØÜaB.Ýzn®Â§Žñ×i<öh‹s¶ÃTˆOMUâ4ŒÒ/ ¦F;t}ÜUßÙ#Êø_Yh6Õ·×?nóùwBK;ÜÓÅ\,žAÑs‚¨O×âò1¶ÙÆg~œµ)øÊó,u@°®úoàØG®qW<í|”tqÍ? }èºæ«ùYèÔï0gNMXý˜û#?ãйÿ1ªá‡ endstream endobj 314 0 obj << /Length 3023 /Filter /FlateDecode >> stream xÚµY[³Û¶~÷¯P;™)5±X‚àõÑMíŒ;IãéœiÒ©û€CBjŠTx±}þ}÷ ÒÑiû’ —°»Xì~»L6‡M²ùþUòÂÿŸ^ýñÊ7ªŒS•g›‡ý&Më8/6…V±Öéæ¡Ýü3z8ÚíN'iôþ¼Ý¥E$½“é·Ð[L·ý×Ã_`£b£T\çyŠ©<εÚìÒ*®jÅý4ïGg[Xë¾;Ú¡?àÒM«"RgYÁ¤?š±Ù¦etdb•¿æFš(ÍÇ¥p\묠ãvªÔqšç›]–ÆuRñ.j»S*Í£Ÿ·uÙ®NÈ{™Gó ÿG  }kÇýÒ­CY4Œ]ËÝaÏÿ¨­"û;f£ÚÔq]3¨¼¤ˆ ä!Uq•ŠÐ1ðP”üWà_¡TôåhG&*;0·i]DûaäqÃý©q ¤Šf‡”L޳k:Ë$nºZ1»“Ý5C?-§õó7›4vš€ÅLƒîyê ícXü¾²ç²Ul«"×Cë ;-“ýÀÚ(7 ^©+Ô†®ÊX§ù&“L þÍs¥U%¨ãBô@šB+GÓU–óøÛu÷\‡aÅfðÖJ8mÇO…çZ‘q9‰ÆÐÖSõmf7ô<0=M³=a›Ä£1#ÿ¼ò³‡þzojÐ|ÂaÔv¿ÒõM·´Bò1ÉÛ7æ<-™m }Å3hñ4OÍèÎ3¿Ûk1ƒ@ÿ€ö }øó;ày¸än ŸtRâåôL0{Gc¿Î¶ŸÜcgy‹v4xú~(HкÙïO^©ºx%¤|âÎ#Ì”~ƬÛÑ뇑£íÎܺh&Õ^Øz3}Н$/ ¦ëbsâ~ îŠÏ„¾TZQÂåµ<Šòp+U¶A×i\ÏòãQü÷y›`úÎÎøžxSrT0ùh&×pó`ÁóÍã“gÁÜì>ã®VéÜ'êÞ»×Îõ–. |Ðt¾ô²èLúº§¼ZkÜÜ»¬¹aÅ«®³ìzßðâ4ho’ka=–¬G¾œR.'•»ò¶åÆ Æ"­áŠ~ä)´d…’ÅU¢vX±ô«ÜÔ?}sk€Ë¹yc|}Òa4'¿Û*=ð{‚Σ5ó$Lído9ÀPó<ú·mdÀõ¥T'uýÛû«•Gò»À'\ÍElŠb©/áÑxºNT>!` ›¹#„÷¸Žÿ·pÅ Âå/—Ýð€˜V„A‡ÈÁ/OâPÌÕ>®¶še— C`&Ó`ó‘ÜL²R šJV€/† CG&€Ð¿¾Áp!yä‰Ý>téAÃ!'ðãÒ Ì@Ì=áà«e)úorŒÐ¶üÂe—ÉÎÝý÷mD¸NâñåQ`ðD!O—JÊêmü*Ip™À9°Atr’{~—:ÖªÜ4¿çƒ|œðá.^c8ÂBŒ ¬ä*Øé #Œ/FU¨Xåõo`p·¯‰ØVQ+9!”ø+»YðÔM¼¥I†X…T2ÕTgqUæ×Qi´ˆcWPIv©ýcÕÙ§ÿ‹gîQ“ädÂ×x앾ar€}´'î­Á;mla`[‘ô÷KßàŽ²Š¶ޤUÊ¢{’3zßZC9í2,¤½Š¥Ãepû{¸xØšó‘ûžøÊ—ge¾úrî~W‡—_W)oèiï jÈ9òQ3LC¸Zuôn‹rŒ|€ë§Ùô…æ*‰0èóp3ŒLðYaÇ🄚¾ÒxÎ(ˆ“VnêÍ4}v’Víä!ªÐ×*8Y~P¦wÓ øÈTzå—Ð4C ý A,=ð¿W%÷(‚ÁdÑÉÚ™m‘~/;óÛÑàX.bBGŒ`ýľ]g;îÙö@°Ù ÂåtÏ¡™ÎztÍY‰&Äÿr¬mRãè5'“,ÙãêA òáåAÜqDCFhðE?÷“i•Çœ®ös×»¨ÕxvÃèó¦U‚+Ýú“ˆCzÓ8â]¶äoi9^u“fü @[brœ@dé­4PbÐqmé̯„p©‰œκ‰ÇÉ"ñu#¶nñvRñl”¸Ñq5%ìzSâgV_é ÞY¶”w”5>W–m®Dt¢¢w‚GYx)­A˜‹Ýܾ„éaÊ‹¡s¤Otœ%ŵûdEÚ³dßóhhÉ'ö¢ŒCo ÇŒ—„Kk¶>PÝËîõ'R{^³ÚóJÔ½ƒè5s{ ‘³)$aÒ:ðÁØsÓÍ{ÓÈrv­8éæ•øŽÚ³*ÖõêÞ‚Ìë¹*kuP7¨Ò$ú¹·…O 'ŽG~Ý,É"1ƒZ F¯å¬‚ò Œ™»ý@{‡ùª]³;os€d§;.ºˆK­泬†‹h,Ÿ2Úƒ¯= ƒ>:¾ß KñGŸ]B£#Y*$¤5𺠞“]€9&;˜ /î:+ U*}n9ËDèÍl{` ÊÁ9Œ¬Ð%‡PúI/Äd–ó«ž;£¼ñ±­ìD0K¦$D€Ó`_”÷$>È×ü&p#)³è[^\ï™v0ÂCmï9ï@ßUµp+£{\¤R)®ôàp"H‡ žÏI´“ÚŸbÆ—yU¬G‘ÅÐ.ŠÀР܇Q´æÙÊŒ>~X *¢– Œ`}n7»»¢qÒ(lí¼–B˜a˜ëLX8}ÊRŸ>eR „Kp_˜k[Ÿ~8¼3Úu`:/åŒqXrlf‚V~÷í·xË¥ŠÞœ2æL’_zœ•Æ.ÄDoŠ!7&.ù¸¦4 …Dq—Y¼æß·W‡~p<Ð:C@ìe¯ù£JÓ‚ê)`+Ö ¿I=ÙP†ª‹HÛKÇXÊáažò_ÇuÌ¢ ë<°–µPQ©F—1Ò-Äã!¿Ì¢ ArÁeâTÊ>/"S ˜B$úxðÎE4­)å3”’Ãݼg½ú"Ð_@9Ÿ8!—ªñ% „·CI¨¬‡à5c¼óÅ!©JT² [Ùû¿Ê:5œ!DX r¬‚·ƒ“íö;ûõ –oæb7(‹äY‚ßF¡r²ädë2,o7{½8_P. OY ðÇ7và –#áV+ƒ ;t “€ôò­$‹DU–b0e”sývf…Ï¥„0Þ…òôA/Uuï¯8‚¯BœäÓrRÉPW`gøqƒ$ŒòsºFûœ;‹"5§—Ïõòö3%°­Ö‰ ¦ò}òÍ#}S$¯²~cL#ù6‰fõg˜6¹þÒ¤:‰Jö Öž)‰$÷öÙפþ@—r©6á{/ù€ƒÂú1]¢{žìÕ„œHI4VÛÀ? l¹ž™^>Z`‡í  ð|ç¦9–ÌÜr['ù•$`»€Qdá5ƒ¸i­*ÅÄŸ%>èñ¸$0óýNÀiY™yÓ ƒžyÁßÀ`ø…]øû…Í·Ý¿FqÖoï›T%±J*0ˆ2†'ì?X‡4o^ý‡G=J endstream endobj 330 0 obj << /Length 3267 /Filter /FlateDecode >> stream xÚZY“ÛÆ~ׯØÒK°U"LÄ•<ɶ¤ÄQb•­ÊQqf‰!9°P»›ÊOw=8v±N^8WÏÑ÷noŽ7Û›¯¶Ú~ûùÕ7ï‹›2,³8»ù|¸Éã›,OÂ(§QuóÀVn°Õí&ÞeÁ½Nè½ÝwíÞÐ(K‚¶Ã¬köõõ6 *¿Á5h?šÁ>|ó©úe¥ÜÅlÕR›ûÛMð¶3wlsÁЇ·›]”¿oyxÏ?–—¿J¯Ó‹ÿp¡VVø¼½išvà~tÖèLwç†Ît·ÿüüἉ¢°L»O|\Ûý¾sÞZl µŸ¾½zWÛžï,i¹©ó8Ý}2:±§'€r²ÚÛúÀ8ŸOŽaò2p {4öæÚÛ•³GÝñ“õ3ü¬íŒ&Ìå(÷ºgïLͯ(‚“«*Û ßt×ýádô*Û —:â’ÓÇöÈyKè¨%¨4 þe÷`eœJéöç»Üíã-mi¯°¨ÓÄ–k‡‘Çrs´í”4QÄÒ“›5¤Íí&ÙæAå4± &/]{ìçdKø_÷¼tÂó’Û·U{ç)-ãQü“(žq×î]]£'ÂÈÅ^sWkohÑBVùvR¯pR²ç(<•îa°èƒéª>$¢F‚p´ ËÝn‰õßo‹D¨»c܉ã•EŸãö^8̽CÛ}ŸßÅm?´l(˜~<Ão:^;ëw[=§7ü ¯®9êùÓ©Ø/RâOèz‘;[Ž,ËfÒÃàG=ï§â xnÖÅñ ‰Òepm£ý·™<.÷K¼cû0ئ§ =Æ¿DÉÎ^ú×:"y}×ìÍ¥¿Ö:ž]Z &?IÁŽlo]L’8;†$ÕCÒŒi*¼„·8ž×kbË{ÿö§¼—•(σÅúìrµžE°¿ž½ÉYÞõÐÍ• Ô4=-°Xqÿbއ‘éÄÔ(ªËP¡/"CO(’?¥Èš•…p‰ýLØÇ”xæ´çeûŠ•í›ßèL½€Dm§3g¾ðZnfûfÔ«Sï] нN…U¬Â”:6ê"ÁÇræ@ÿV›HAã™åNâ¬æÙ…m敦ÅÂSÄkÌ2YcÇ×€Fô.Fk·%b{!ì:+ÖÙõàã[ˆyÔùÑŒŠÆåLztE^û¯Ç¡%*¦ìÿžIm’‡Y´ó°¦îÉ…·ÑTLáÝ.2’슰ˆÓ_˜ “Í’d;í”_É‚%ÉHØÿ©¥ßºáLYãšFR\“Œ¸ýÜž-úYr¢ Áö…4ðp­Çt“b×aW^n×Lêìõko¹¬"yB¢\äümU ãh&øP>¼|!~x"Q5NlÖh÷\œ]ö‹àr|:âKYúôç+ä_ˆ×Zû–›¶¦Eðö–ìõuh7dÏYêZ ›ýQ@ D¼=“˜ZehB&6ŠÓàƒ¤?Lþ< ¾k›½½ ýs.³8D$†v¿=hޘͬBÌõ#ÂÈo» ;bqÏ^ÄãÌWÚ¨×[‹Žؽk`-¹ï%Ñð0%¯ÝÑœ‚ÿ1«ä‚±UQ“\rZ¢œÊSî X`ÐkÙl®«„kFIë½™Dž†Ë y*òöœqYÆÅ¨{fi¾š’ÆE˜F©‡”C3Ô“³H‹²taÌîÂê s”†'§ •ç…ª<è³Jø£Ñ:ˆ£ŠRàP7è¡#M°¢¥…M¹ ó²|1bQÀþd-KB¤Åˆ³z¯”¯¥îš©ÊFÑTTäí¨ ÍwNoçÑ3Å §:Ý_O®ÖÍ3m¥C羉7MöC{oP)¦éCמõªõW䢽½”dY™Õ¿îÏ9xbV’^³j0PˆÐÜ `Üj8°CHST,©õ× âé({ÿõŠò[oªrð'!ý:•r©‡o”˜ïVò€ù¦½QçD«A `–W1„O§d›¦"9ó¯Q3}g:Ê¥7i’²+Ç"<ç@xKêu¹@±éÜ3¶Vü­çy­YMß±sHÖ»ûR@£S$ð×ÚtÞ ôm}åHöw~µòð¾ÚA³x‹@« ·5éÎB,(U¹vòÙbdßøØ—«?J€éÍuj{Ð;É[¸ä³?à‰Üss“­Ð²‘?ÇèejaŠÉÂ<ݵ÷ Q¹|ú`„ Ê]¼ÂÎêí£.¼ø)@h–ò‡¬vÌ[3ŸÂQG2Äý}[·¢f9e¸¬ÁʽcÁN~ш÷ÈÒ§ÏÒõÁ> z/ …NŽWžM÷eZ Y&Ëà[«ÑVœîwú~ƒ¦v½.wÖÞU7åa”Þ9Ôæ‘âÛÂéÊòÎ ‘—¸16aËjT…Y‘>± BÕ2ãŒE»” GêÅÝÁì-¦ˆåsËEà'³043O1xè.ýø‹!ïŸ ­œ[ȧ²¹ô>àέ|Kå¹™©éF¨3ÀÀ#šB¥K¸PÂÅ—™Ôö^”´ÞR|P‰°n«îžÚNÉ%©r3ÖU¯°þ_ÔÆ›nE{³±æÈßÀ£IÓ1œ8žáD€³^XÙ@#™x]>èE¬oƒ£ãŸ‹Qeòœ©¦$ Šä¦ô¨”¿ô¯¤+e˜•£Xñ÷=²·?q¾$Ÿ®Øqzì¿HñC*uÃ*¶\.Û€q…)»Û]cµ8¡Ÿ3ÙFž´&‹ÇS*6’jK2U[ø%ç¶üÇðh§r»¢Õx ëGÃJ²»0ž¼ÆêÓ5§êÍbm6N\W5MÏù‚®&‹ô♽æçºÇx7ç¯I&ç´|É‹Q’dž‘ì7¾^>½@û•ê;—?û±L4¨ÎQ >™'¯ñ´rÇ'ûlàs™FL×Ë+ÊÔÉÃ5þ‡qç+ +×eB6}“zæ–ÇÿÙÜDeF§QEXj/@Þ}~õ_&3M] endstream endobj 339 0 obj << /Length 3422 /Filter /FlateDecode >> stream xÚZIãÆ¾÷¯r1˜¦Y¬âæ›ØÎ‰ƒd&0ÛŽÈnÑC‘ IM»ƒüø¼­RlONªõñÕ[¿z¥äðtHßß%òûÍû»/¿+U\åi~xÿx(ó¸2æ:VŒ4‡Ÿ¢·ÃýƒÎt´œº[&:Þ§etª/K;ñÔó}ZD­´»¾çVÓÍÇë,{–“Ì?µC;Õ½P‡c{Yfžù÷íåþ¾ÐÆ÷Y’Eÿšvš—zhºáÉòÒÎBï2²|ê_~yÿçÃ2tž¥â*“ó|àÕ°Të¨çvÀã,ñ¤MÔ=òÔ W|ÆNÍ+yzy橵'¡yç…çÆ«ÌBÓŸ Øûò;:q–¥(üäðqY–Ì'¨àO³èoSC’.2&„¿pŠ\G¿¶GÑ Õ”Të²bJ_ƒSSò×IQØk¦óLBÅTojЍæîÜþûÚ‚zx?Œ£Oíxn—©;rùÈ2æÔeT½?ÉFf;ܽœ,9Ü— ÿüõ{Ùæ™Å4N‹ˆü¿Ï§vj?Ý“šIµÉZ© …4RfÅŽ€pöYêÔ×—78ZˆÖpÚoàçSdžÎpn¡ôs¢Ì4˲nà_/\}ÁgÁm^ŠD“Z§®‘1Ï´&i-‰S—Ñ' FT‡ÕÁ3>øÐ>ÖÄ8‰ÚÕ|n˜¨§–Ç©­—¶Áƒ'~öe³ nš¶áf7ˆ…VY)Y¥úôãtŸ)`u¹5ÀÔÄEê’Ñ"}:<ò*'MÌé,úÓè”I'µ“Â’À-ñHõ IÓ…J ai•¯…&æ5wK7,汊jÛ÷Êð /ܾ\—…ctº…ëdçã4º8„&Y6ð²Eô‰í5ñýñ ÛÊuvDÙ( ñ³Òæ»ûRG–ê,Ÿ_€RúFhÉüãu8âéæ=£!^$dݪ9-ã¢TVyß6Ýž‚ÓØø5gŽ¡×ݰö©8ÍS n• n©7 ÒŽ×i:Z‘ä``nû–ÎðÙ÷ã ’Š¨¾ Ÿ“•@çȆ-Ò.üÚ8Ì=++Tlós§Z†¬Î9ðÃÌ8ü’†"ë€aàH³W&XÇÁ÷…îi¼ö쵩 wO‘ã€9²,AŠ”œKÙßb·Äro]©Ø˜Ô*Å}$Ó¾¹QqRæÎ¥Ûâ‘Èu³²eÂ7YwM ·Žö8òs’%ûÖ§2'Fípµgºˆso‡@U1}s7Û¯‘s—Êe‰‚² \êi™¿âH¡!h¥ÙZ¾¯°XÆÆIâ2uçzzÙX+ØœC”lrð‡=äÛßêã‚(†QÔC ðì–ãxæ,×T…@4·' öÙ¨°évjþyšÆëų0²2ÎÀ»VÂø½ˆö4 EΚúY ì »3Ï£oŒÓ™;¯‰à|ÈI‹tÎù¥Ù/hÞd7âC,!k¾ƒlí?îb! øúî㽂x¢¨…‚lûÛ"éC'q¹†6؉±A¼%—òÈ@XT'yµN,:TÎ^hÔ±ý†'!tô–æÈY6cææf°]I :G‘“tÑ+…ônh:1ºü’ÍãÜ’:uß= ÜtÙ ­H£GÌj8Ñ Ì­Œ[™€7îöÑ'“2‚ÄH ¦v–¨G¶‹¤FOrç,Ht`¤\¾ºÈ©EúešWŒqøÄ dà®MþØPßw£æ\2µ§„^@«BÄNHÇ~œé¤:úa\d3¡‚z±u'Ã}ж 7×›Ûgž  `—å‹­šï&3¨êä”›àeýH¶=~Œ_–&Ñž]“¤l›8ê? 4ó:‚p8áíZxº6Û¸{iuƒwÄÑ4IW¥¯@År cÛÚ 9Ô‡KIÒ<Þt î;£D­ €—™=¾/B´žÅ*ß uòÖoßßýûN‰G+SŪÈ:Éâ2;Ïw?ý’˜ƒïƺ*Ï´ò|€Û‚.¡ÕÞÝýëØ«ï©,µÒD)Ï”½ržÛËD§DÏ–Gvn(*ΫÂßúðnÒ>Îq­w¯¥:¼”¢éå…½¥ƒ”z)wr±ÃˆöY|·æq’D£|ñ ÚÝ€…<)™•–`Ö¦$åK`ª0qfÊý$ˆ†ENVz”KÚ¿R`Þ»P8.¥Ðå¬ íÄW’©`v¼°aÇ>¤€Ï³’)AgÅ[ «U©ÿîn®-W˜Éìî UFâpt8a,~(,¦ pœAdª|É;·ï¶»(ðÔÌ¿xñ[÷¹˜¼Bm¡.žJØ´ámø j7tp¶LÁéÞ«Y+GÔȰ`RËR1 õ™¬ +ß]êc{£D˜ð¸:‹”Zæ…'Žœ¦ñút²)‡B›Å…-[°ÙFÉ4@Qž?r¦œŠçnä!BW‰®Öæ ãμmeµòŽ…W ¥©ÈÈ>I”U¥*ëИìåŠQò°C|¾åQ—@Lb3L¹Å¶eõjàu6­¹$41è°÷†¶ñ=|!ÒÀœà:±0´->C#-Ú¡Ýp=4·yE dÐÕ ;½áàä_KpUÃ)wä4WWÚ¿ò’Rí£’Çh8‚u@Qº³èÝÈÉš±L`¥‚xAŽÞ÷wW à$XVýBvüz¥u´·O!;ž[z°â.ÅKüµ\u¦nœ„쇫#%ˆ+·øh[»_æQZáÐ!_Óô׃Eme.!Ö…z‘FH£¼%Œ0<ÉÝ#EY¼VÊ«’X•Ʀ¿w®€‹v_†ˆÝ~' ›X§®Åá«b{¯~´ÄWžê3o:NÔΛÅCî÷v …0KI8Óq±)ÿ1‚«Ê­ˆpdàßüœA]ê' X“ÄœO‘ ë±Úƒ-Ì_½½œe^“i¡c£«]™ª@¦Ô£4¿}ýÂ¥›7þ4.w„ ¼’¡V¯‰8¯â"ujý ~ÿi›²ØÊ™?á+Щí3½Î²ØlJïûÏ&Z¯¯(Þ^íÜ LôbÜT’ýÿ^ÚµCÿÕ©Õ>¹ `D]:8–àpt]m^²,X…~=kþÞÒqÑ9“2ŸÁàcÝSÄŠcÁ3“vu‡{ï0`"»Î‘o†‰¸",Ƭþ ±>!ñà )ùòöºåu¬t –äYPš)Ö¥|ù÷<®^¿ó‚"™åç¼pïöù ÏnJDß²@*ÏåY~Ûßðß`pþ¯ðŸ_¥E¨ö…Ž9’뎿t¤ GiZÃ=WÓWk¾}÷?±œ< endstream endobj 345 0 obj << /Length 3669 /Filter /FlateDecode >> stream xÚZYÜÆ~ׯè!滛ݼí$ˆ Û½$w†^9&9šÿúÔÕ¼–#é‰}wuUõWG3ØíwÁîoùþôéÍ»ŸÓ]ægqï>=í’p'ÚW ÔŠÝ/ÞãyÚæîA+íU=~CïÔ•}_Üx9TuÉÅá …üÜõmǃy’öšvBi¥k>¾+›»0õdL_Öe>Tmsõ©-î”w(»òî·Oÿ|÷s˜Í(×:öã,ƒcá°/™N)?ˆC7¢o² ”MíãÝC{¿Ãö8÷ Mâ'±Ú=Àä,®äuÛã\ µø5rí¿AaÑ ²ýp°ÃkC$q<„£N «+/xb*|í]˜x_seqÏm];Øa¬‘€¼>·5‰ g7ýPÚÂçf¡¤î|ïûÓFšÐ+Ê'{®\Ëð_Ÿ*Î|­•£¸»‹”Glœ-óC¹‘Oç†DÌ;1Õ=Wlמ›‚ËÌW(ä¨! iñ¢ãæöi5Xì€``Q5{lÕÔšx-rê…[žÚn5“µ¸D|QJûÑŠ/¯åÑûw± ¼O’I–ÉþåÁâ^_*Úšs‹'ÍR×Ï­D˯몢(·4]¹ÜŸxF^=]ù<°Š•öÅíÛ_AªG.ÿDÁÇÒ±"_C›bß?Éäù"xè`yÜqÉQå@‘ÊAT øÖ8Ýg†`¹íª}Õ,ÕôÌh½¶çÊmA6ÊÝ/;VIeü̘%)Ÿ6un‹R£îõ9*èù†êE~ŒmSl-øA`ÆÅRårȯ—ÓÚ×ñZ‘I – –?yÛ5sÍbÖYèb.@aÔYQX#MNaa+ì|Ú¨°T#区„Û;U6¾É– åE‚tE™—Ö±¶Q8ÐLfNC‡Î6=q´x^P&"ýqo+Âé ó*™AŠ+ˆvB˨J¨¶±*Á¼q‡Q{¹Ùž:·Ö Õš«® ôã¶ê=2…Øm u†bÞ6r-PÍj²LÐGp_Æ+™Úñ—0–‹#‚a™?|ËY ”7PéÅí-#…€™$…É/3zKÛ_—$Ùw8T¥ÛIÊ «Á@ë\äÄ…Q QÊÄÍ;E¨Ñ r°»uÃìÀ%µ¡|A)ÇÈj±ÓÆ LB²à Z©SÅk§¡÷…V{}ãÔŸ.îÌ®ÀF|ià= ¸¿w¶¬­ÞºzÔ]„<:¦/Ç;âΠuaâ§iÆ“µo`FÞÇ¡kŸï4ÃbäP¯[]s9oë¶ÛðSP—S_»U? #-€,\j3÷PznÓybsœø¡k@¾Ü’PCQºœ¹[™£¤dà.¶Ì¼‰Þ˜¥iµÝ•»ùhHÙj¦sŠ`Lå¾r]Œ£S±6=¯--Ü„(Ód@4s¥ílÞU'¼UØepŸc¿¡_J‡~˜éÄ·ÏÛ¾Jš¥_7 ÆÄ‰C‚•Woxž1hè´\'gØŠ _ðÚAz5½+.ä ,2â‰e©C'K ¢l|û³ÔWA¼d3-ƒrY‹°À®RÉ11Èã[P”E)ISˆÕW]ÉÛ×[eÊ'ÿûsÿDf¶ªrã&˜ÔO²Ñn_`o²ˆtdâÐ{´€SB*„%'ÛÄ`Õò§µè,±Oº"ÅÄbhßD+8ñ:èЖ0ÁòÇk!ó›kàg®VÍ3 BøLˆˆcߟœï‡#ŠŽ®ë¥wä;l©na’}êêÀW“’; Küf(ds]‘í™+¬^çZÎÓOJÅŒJÜbmfÉf‡Ç*ž —Š`+1ãVìA—c#êpœ6´ö ;¯L‹,2†UD &“Hœ­iÂjm®ÑÝè…¹}ç@Š*$μ½ÿP1:%3¯ÁsïÎýážË¯ %×$ðëÀ´RÜŒÙ"é¥B5h|®èZk1ɰÞÉNþ4×Õóß\¬]ØjP` cIЛ£øùÔ²¬kŠë‚·UGÆ¢ìûà-òã`­rH›ÐlÔüÄ#Õ (é¨LÂÊ_•6ľ··Ý¶Ït$á\D‡]ÉîtXþœØb&‹˜þž ™û«B¸6œ‰à1ô ¥3]^¬]¥$ ’Ù5¢âû(h©^sºQ…ÐÁøü(™=O©—“Ç™ ÇII=Ê%‹Ó Ý’8¦DEÏœiuõåþ8Kð¢õå CÃýU³˜9 Ò ç AîYõ§%pæ×j÷ûºœÖ½Éµ§®â»Q¡QÓ­èû])»?ÆDÞ¿ÙÞëéVʵ£¶Û7ló²hº,³‡+ŽÐ*^¢[5òêâ³S˜S¸„—ÁšB× ò‘CX®éî`çBVØ5^& M©àt*ž*SªÐ6b}î¯s zLèÖ‡Y&O\4þ ä,·P—` ëoŠÓ•RÓjJ‡+—[We£_NUISOÈ£7p^~œp†{èË”7ºlnÄ”vä<›(˜6v¼ålC$ï ÐÁH…õVšÁ§ ß1áˆt#Zq¯€øÞ>TG‚Ðéaðé\/Ò1‹Ù¤yRÔ –³omp·Ü2µ=É•xXùž¥St› {ûôlÏú|Åÿ‹¡XÜöŒ²7+ïXß°§úÓµá>¡1KÅ! -¥Àoø¿UmkiÃX®”¼Ê<2¤ž)ÄÂU(OõÔÀpE¥\ÝTÓÉ B9 ^µ ^á0…ã¢dA¶|ù¯„‹p` ³Àwä˜íCY߈”LOŒÄj´Øv㟠ãë$œïäïl$°R?ŠÓo¾Çé˜{º¹¸øq¨¹~$»w3¯,Þ˜LçgÊŠ4Ü?¸ó!ÿÑž!hÓÄ9ìayèprËUqÔãEF“»(& ‘,íSëtÉ ðQ»œ^ëB÷¼%c´ËÝ=—;&¡ÆÏm”tÇ_¦„³&PŸd$“å‘0öfo ý|)— †ÎÕÙu>¹Jaà¯èaèº?üØB‘z_í÷' ÐQ‹/$é<9£ä-uÿ;³h\‚gÚÙU8R¨E¶š¨'µÿºúû§7¼A§<Ø)üãJ±Ff—ßüò[°+ Žáë,Ý]hÔq§’ÀôÇëÝÇ7ÿá·Tº‹À™JXÓµdá.ËÀ›Ò oJ%»†Š^T|…µ„~êFq˜gbi±D1ùÊÇô_‹<ÀÑY,Ͼðý³ìÚeË~âÖUǰÞmP”_ª¼\í{¢…ÁQ8».2…>5Õò1n¼—êh‡’ÜŸù¢½=:›ù„…úp'D9PŒaþ©ŠP^È8¤ä=~â àŽâTqË©CÇ;ó8µfž›Û^Co¯ °†sÏc#’€æûY` 0‰,Âì<‡¶«\f–¯ú¼=wv_ò¶!ñží®Üä$+ípî(P«â3)o Þ¦Pô=7_ñðüÔµW„E’¥ãá‘õ/zæ ¢åpß5–‚d‚t¦È3qÿÍú2ýŠ‡Õ endstream endobj 352 0 obj << /Length 3283 /Filter /FlateDecode >> stream xÚZK“ä¶ ¾ûWLùMÕŽ¬÷Ã7§âM9‡ØOU*‰sÐHìiyÕRGT»wüëàõèÖØ¾L“  Þšàáõ!xøëþþùù‹¯>¥_fQöð|x(2¿L’‡,ý0'Hóðï›Ç§8.¼©íÚþ•Ç¥w®¦ÉŒ=ª®£Â»Z,¾ñd¸è©Àc5Õ ?Ꙇ—ǧ4õ~6õ„¥¶·“©]=øS&‘ñzJI;aǵ¦¨ Ï]«§ë¡Fÿñ)Éïû¾{{üïóßžÂDX} C¿L•UГ$z,CJ¯®z,ÑJ”{PdÌ@*ü8¡ñX…F„äEé=ÍŒICœ<¼4îÞ>¹í¶Î àòœVZ‘ì'ÚkVõ0({)ØkLoI`´ùöřȕó3j‚ýFÐf!okG€E¦¶V‘TŸø¨é1=ŒÃiƒ=…P3êŸôä·ÂÉâI#ï_E"J$ •â´¦áqµÇᢤÉZIïbž‚†ÕCÏOæó„•“ÀË­Õý鬭„z”G fÇ©5@fÅt +Z’3±ZÝÄOZ)¾ÆðÎ^‰Pkq É] fvØTÖäâø–ÐØk!®¾(C“n´ôö¹÷Ö{4fòóWÉð:b@E¹_%.ŠýŒH£Ô{~,o¬z{®FÓ×o8¼öLcáÇîèw*!Gy–%p!><ŒbWA,–B?¶=;Ý|ýé°&jJði}?‰—D¥ñJWh/t…šIO‰ú1šsU/ê?ãÙÓÞ•†:òúFѰšì¼…;â,—N~M$ǃéö^ðBˆa¸’b¤~š•t‹`ÿú^ΑŸg¹[€éd*ÑVø9\ºN®Køþÿ]Œ^½0HF—¹w=¶.{ô䡟áïÐS¸õ˜®Ðê®YÈÃh"ãFØ UO'‘ŸéVâǪ;<-º ÎVæÞ7ìK¢4ÜÊ<"‡òË#]Pu¶VÞ0G)^¼¶ö0Ç+þ½XƒÿVø¹3- 8‰ß°6½8Í—jîÍ_;)!;Fù°‰MÊõ_vŒšföbUÛÃiÁÖPâ<…”aÂÁ™J^·#ù…I‘`F ¦”¿ýáG8 ã©bIôB?iðoìdë±=OØ­’¸ES¾íÝpk/‹7à˜ßXxâùtMH˜È}‡:ê¾#G¦²CÿѨkg¨Èn«‘ež'pE²yf¡*pìgn š<îÄ«.Ó@·u%¶ÄKUÓÈK2 Þ;èÍUö–䊈¶Iv—{>¬­ÖŒU\®í/.ü`6?çÖCrØ‹GX £ÞÚÈRØÛÂÁñŠð»XMVŠM3XE)N;¢xPÓ Gy9¾+=Mý"Ïobô€htâ|A^…g‚šÈõ’^â\¼ ™ „—;ÁæÞoǵÂŵ\ãÚo§ÇXŒþRÎH†ç)¤"ƒÊ$/“ÑÙ4í Mí»ñ¯tY3?ò¼›DDéË¥f ˜U •´G#‘l ÐkÛLG…ªúö:=Uã'EØþj(–A d39öyQƒ"ÃæÜ•'†²U£Ç6yÆæPa(2½ˆ¨Ã Z÷ #¢­~$Þ‹u±‹8àÙÕ—]mW6ëöð&žlF§)¼ #ÔË,=^ä¸ÂãñnG>_Y Ÿãø”òÚóíî@¾~V™ Vh½¢‡;gõbµìÄ®÷òOÕí•ÖŠ®c¯¾ˆÇ×{6Ä>eƒÎ¢í«zLE¤wŠ—$~žÌöF`&ËiÌH’ôÕc*êâbKð÷¢oqà/£úb«¼Z‰·Ù·Å†V%fÒï¢\4©^:³]ÍÅ¡fõz"@© §(Ÿ®;—XÉ´ÑNõšä‡ÞJ´§bîE‚V;\l' á‡Xã^FBCQÎw³z”KX€…J€F@(`Î6KÀ®_a2Dµ^v¤QYÀ,¡Ô ©ÆqàÃ× ¾–ð$©°† 4{Ë93Nùî DÓ¾µfÎÛ×¶¯:NðÖ 'ð×¾c<¼a±®úÂLc-ŸÐÜzõÒr@+Fó‹p߸-šïòMœÛ¿n%5¬ÎgÔc¥+myé>‚ܘ׬ÛBñ]l^Cïrï÷³§ç£Yå…ËH#F­Ö‚㡪uÑ¥ÓÙ .ÑzRò‰'ÄɃ“#¦w‰RqL+¥5ÉR'ò&øiÐ¥X¿Ìëìíoh¹2ÇX²tŽ!Q^º¸@P „>LCŠ®bä^Ç5³Eì}×™KµxÛeš½PŒh½Ø™ƒÞ*Þ$Ëæ´ŸÇ(çE¤´ãàói{ç­÷.òðöý‡ÿç‘¥Á±[Ò1hxüÞDE†–­¸~†ÅTö›€æ™w †Äñ58ßvǹD`TM0!O!U£“•dæzˆjV¦PR3Jg9#c¤íáýzé¶Q.wtY¼(xÌ6%vÑ-Å©X?[m¯¿K¤"s¤’Ä!‡,~mE‡É«™Ö8Â Ž•g{ßlnØH/’sGò­SÓ‡¬áU¯¼;Š\AI£E4©F]?ŒFF1b3Aஆ%ØÉþÞù«(ZräÄ\*²p"~Ǻ»pÇJEWœµ§&㥥ŒaTİ_ŒáAöeÊB×a“á–bée’¾ë±lw’Ï] >늗QVzxè¥\)\É[„.úÌ÷¶5âSÈ}/D\ARDª“Øœ[éþ}v¡ñÎnB?¡‘îÖ\& r?¹í  ¥J~eC7ĵð`GT ^+%Ï·|2DŠáÌõ2i°joÑ Æ­×qD°:XwH³¹CJ£¹¢y×±ocãkÝZâü{@qsº)mΤ¿×Å[Ú˜…–ÜQúUuñ„©f…öʤãt™;,’wH€fÿÂTŠ¥C[ÄhaQ3 (¤á•¸î÷xƒú†˜Ã¥¯9U"»tq6-SQŽc;µ}{Ò²ä)N#å[:Õçí ¥bìǵÌ! Ìõ@¥$¦ Êà”ÜÙ¢(¼Ü´öÜ çoð!'×"Ú¹°š–;¬¨ROR‘Kо:éO§&nÇV¸”ž±váâEÞt´V™Ž å‘d(¡îb¬Æ ˜NEm_¹ƒ`~‘Ýöá¡ÌØ™÷ß¹Å$a¦D&r§Ÿiâsw”Yºê÷£:C”'E°Ü¿–£6žGø=·ŸMç<œÖ¥X!/¨™ý;ÔGAéGù\z}D¸¤´‡¨;ò)ã |ªD·OwÃGæ·>ß e¡ÁF7h.©‚$ë¢%ë­[½"ÀÁ“Føú²ÅͽB‰Ërí{üÇÄDž¤[þr/?“?¸¾ãÐK?ˆÒwžp—uñŠqøw­$!9ʶâˆÖž¹![lýéo¶¨˜¢å#Uå˲¥|Òô  tW›=-)K?N“­”¸óKé/+ ÜÕ½¦çk˸•Q°jµ:Â!©4ó3Š ÛBi2l[‹¨Õ÷"äáF]ÂöÓ§´ä(GpM”$E“}iÕ‰+¶êCw­šuJÕ­HˆÄ"œ•€"T*êþãw?g!¸tšDY)ñnÃè±b¢v!ns;¥a>÷Ta¬;~šÏ4"òÎMäJH‰¸æì{ôCpš.ÇÔ»ò°Ý#*Ì)bG‘»î‡]Š"!hß%üe9.%㛸`•Ð-?…qòùKŒÑ„ÕâTÚúQmÝ;«Ÿ ‚Û|© ù4›yÌÞlá1w õ•ÂÆ›æÝ5ryõ1ü]!L4‰#ˆ3Kµåï¯@#Ÿ›¦„ò)Ð*†/ÂØðÝ¥;1“|£…9äžkµêFÔ"‰àái­Úâ`š}Î%Р6.ùÃö±Þ°ñª>à™9djõ*{Æ©–ŠfÒ¡Ú`Ù«„bÇlkË;»û_çÆOòÅ0\¾«R‡à°eý»ˆÎ€SÛ4î>f†« Š¿ñãåsvG»\`um¬”*í¥vªÍ vuU:]c„×Òm;&Í-Óå;ɯ+‡ÂÕ7Bhwì+Œü,˜µþÅ­RÈ“»‹(÷ÞÇ;2©™0tK$âjû%ŽeÁ›Ôý(8s¼B¨M7ÞtD,!Ú„ Að/×Å+ ÊT“tûxE' ÖŸLº¼Žü#Í^ÄŠüx®Ð ÷Î(%5ç>«"9 BQIÌém%ßè?càƒÇ Ó°­Mó?o¬|ñ:X‹çŸÿé! ? ŠR'ªs÷ z½çÛç/þ,¨«C endstream endobj 356 0 obj << /Length 3128 /Filter /FlateDecode >> stream xÚ­Ëvã¶uï¯Ð®R;â|³»IOfÎôLš6q=I´HYŒ)B!!»îéÇ÷¾@‚ÔÙÚ¸î ÷Ê_Ü/üŧ_ÚonoÞ ’…R^ÇÁâv»HƒE’†žJ“Åm¹øizùj­T/?uúxèW¿ÜþõýÇl‘{y;a‡¿X«Ì s^ÿÙ¬Öa.ëÛ`©·¦j´Ñí*È–« ]Vm]ÑÈð2£yéªB0vWÓTSëÖ"d¸¾[­ãxùkµþ–FÈýds_·÷M%qC‚Œ‡½py»«Wj);6…° Ë€/ÙTlÛ]]="³Ui—Àà™Uä3].Y÷Ý*VKP°qª¸HyiÁZë°×‰ŸÈE–-»ª?6¨–,gÅ¬àæ¾Ò{T@eºzàQ3æÝjùÁò Wì@ÖšÅáu,1tF‰a@Ø´Š,8úMÑ ƒN›Â6`Geè„é‚Ld±é&úž£ _>ítSÁò4ô—·« Î’áUYîÕxž?wó¥î¸5š§æŒòì°!#KadB¶6;î> 3˜áƸHˆÙU]RÆ!iL£Âžˆ“édòGúÈÛvÅœ@ø¢yÛõ`!Ì#µæaЂ,qí8 òÔ9+.(«ÞèHu_õ DPË—N[(M§ËqG 2W¨Y{;šlQ½5*Øž.!YPÜ8 Û£¤SôUCG†àAP¾0Œ–w^‚!6lI8çpÆ3û‘ùã;mÉ{DN(|/O¥ÿ³½v>¾—&]º=¶ä¤<.ˆ.éÄ—~bu +îmgßF—-“Àñ^¥¬#ÿ‡’£¥2ˆÔÜ‹´½æùÁ>äÐAÿ*¸ sëŠnƒËwhFÏ.pæ—P¸™ÿ‹¬ e–P޳!FT”¥tdIS|¢0:fÇ;Œž,#¡P¦©…ãʧºix\dô{†GlÐ);ºOÆ]!–)téÈTäåÑÌa‰S 7ÖZÝöuYMÌp",9À±<1°I|å©—e™ ¯Ê—øú¥X… ´?à‚^гØŠ{t8>‹ˆ<l?¬WÇQI×t¹9‹`É}Ý“ÃtPèVv‘Ë…‰½îÒúÈRœŠƒå·…Xo Ƣ㖴…è,Ó‰Gêp?: â!Id.L°¬ÕÜvUSàìwõ!BÏu”œÌQ vÐásÆý,éÃÚèõ¶ÓCÄuWZ×Ùa¤%c@ø–·º>ôd'zDFè‰®ÅøÄ €56\Ô_½ø4{É —âîhª©Ç0;fpæ7ùRŸ³~Ê?¢0™:ÃÈX 5vÑæØu£q@ŽzE'TQM!ï¢MmÉ êV°Â´K=õ@ 0ZŒÃ ^´ì?µ1˜Ñâjk.ð<\’‹|HIIƽÐ&e b&Ù|EŽéa_t &7†­H€}æ{t8;L¹vÇ ¶ØËdY™ªÛ×-Fq?í*ñú„BŽS°8*BP-{ë¾¾£tËrïšZrÁÔò%IdsÞÐfOØ#GhynÖÃî8_~@÷ÊQ7›Í/E\?ðüPÙ0Z@}¬N_{aÙUv=¶ƒ¿UOLgš¬Ãä °ÓÐ¥çÝ2ÉQ„¬[æÙÞÈu*/Œó™7B&%×ÃËtÂN9QÑíl3E{_Íò˜)ÊðÄ,¡è`ŠÖÕlÑÌÖØƒľiH–t;#rrÊ!ÙÚeðÍ3«£Ã:éž²³žJ…—$á©1†lÒïXÅN^­¤áŽÚ/¡ êèWÿ6 Hv´[ Ö$ûÁNG‚t;Cº¼)å÷toÿ\c`Wƒs%/žøŒ2Æh#7ŽfÑd²0‚[ÝTä›aSµ?{®qò¢ Z±k(Õ¾œÊƒy¬:A v|Ð)ëþàÎËrw™oÓbuâv`NÎ&% ^n ã}àEÖ ×/Ì:µokÅG’±?FÐêƒ<¶óµsß(æÉØþeoGï’µ‰ ?b«Í#! U«Íਠó;\öì΀Āºïµ1Îå%/üÝ€+g™ï ¦ïéÛÂV&0"O-m]€í†ÿEL˜— zÂö±º÷meê$¢„ÜöÈö²«º;å¾³Ì^±z‡o eV©Hšd¢8‰v©rdÓ}ùÃéH%©Að~oûu{š&ŸIÁñ>\>«þ”/L`‡kbè{¢ª$(@;æÐÇÄYöŠÝ¹XÎÝe×- °Õ ¹ý°éôÅõCU”œ©@ü=8ã3ç ŽxŒžA4š¿O˜Áp;²‡ "Ö°>v<šBF$²æqc‘Pë£,9ƒAbñâ@®29;謟E=ž&š¡™œ?<í<ÖÕÓ™";½tÌF…0??PK2Wèñ9)"Ö0´OxT¤Ç0ˆ!§Í¦–AqR ÖyÎpýÙ`ÓÑðú2Dd.¦ÈïX›îwœç´¿ó¡AÉCÃw fzÞŽEg6GóâsÃGräÈ.åS˜§Ö9Ü×mËï¢*ÌŠý›¦R¯Æ7Å{ÞQpÃ!•ßôs‰ÕК®hû­îö…K†0+$9üæò&«;ÉBÀáÉåOê.èíIæ329ƒ¤y?À¶*úºÂ[¾ŽÀ¸@ô’»ßŽCq$)WŽt pÈ;Ù\êö†»P¹•Ü£Whñ†îQAòÈ×ñv~Ü…ù­¶É+‰… áˆðµ¢h!t`Ï3÷†„÷œ|NöQMªí]‡Úv_Gñ¹dòlÍO…¿˜Üñ»`Äû†ál|sß(àÚý32<|Œ²í··7¿Ýàôj¡âÀË3µ"ß òh±Ùßüô‹¿(aDóÌO´t¿’Ð ÂúÍâÇ›œCdž‹¾‚Ä—+t‚#¸Jóÿ}d›ø•z*NX[¦øÙ/lª ¹žY >ñ‡«.GsbÅS%E*ñ•¼J¾QG©÷j=«ØK³ø5:RqÓ ‚Â? XGo ®[¦âGóz²ÃѸd±Þù#–+àÌ•%öC¦M!£±½|4_ÍÛµú¡—…o¢U?õ"•²x?îê­¹¢ÕWS”êR=Qê¡h¯¨ïk™8՞ʕ—¥ob”*½(ëø‹éšËÚ{ªV}ªöS–R~ I¾éð#,¥(uøõ¬œQb |o¢Ã,ôb?uø§ìðõ¤Eº¤Ý/Ž­n×%~Q:ri‡Ï›˜F¾ÏŸ¿¯(÷k¹;£ÛËÚƒu6ðÿ°çœ)Z>QTŽ.rù.„›wšô‘[Óƒ¹œ5ߢgÍIÅMp5ï>MvçÊyÝ$Åà_x®Ù îŸ[܇´á=sWÎßEìçAâÂRskW™z¾öo—ñÆø ¬Ä›goR'R"¤à:Œ<¨™ëd²¼ßÿ´±1˜ endstream endobj 360 0 obj << /Length 3703 /Filter /FlateDecode >> stream xÚZK“ã¶¾ûWÌ)¡ªF4iŸ¼¶×µ¹d+ÞK*ÎCA#îR¤ÌÇN&•Ÿ~‰û "Ðh¼èž¢‡_¾‰äûîÓ7ß¾×郊C§úáÓñÁê‡ÔšPÙôáÓáá_A¼Û+¥“àïO»}j‚Ï®v{c“`ؼ^ ¢×ïþýéoß¾Ïò0Oa@(zØkfZñ8€SgÛíc“ýxázÛ =“~‹TüuçYlp¨€b\ç$Ì4`ùU†ê™±=r[ +LZ¡´ §Bú•EÃ…§å*.uQºƒŒ" …4ÏšâìêWæºÃéz6P0pÏJ…y"²û-J¢—SU⢡›ÎÓ jÊz<àÒ±VÔ5ÖkGÊK5H—‚?ýе_H>&”-K¦;al¤EY×Ì—À”; ²p]Õv;À®Là ,—Uô¾gÉÁÀ–ÖU]5®—^SÛ3L®‚÷þ¸ÚzÂ[ï/¾[œERƒ>žPV]YÓ&Š×'Qà꺺ônÉ4ÖE·Å5€T™Ü•žâè@ŒEó àú¥upÿ¸ ; >Ãnd¾¹‡ê —ºØlêâˆwŸ¨8xîÚñ²hM­‰¬Ú:wÄ;\º[V¦Ì—Äâi éìŠFZå C©àOÿzÆs{’ƒ`b%ÜcïdÚ¹×ÆÆJ× \‹½1Ά‡¸Ú9†‰PPŒ!–"ãõpqA¤&‰yç&1"p,-¥Ç”¢sÌ]v®œôx"í–†šõæKÕ<Ëx'éS»£ |naÇL|‡Öä¾=»—“ósx² `RÙ‚´çë.¡Û{Ûomnìi:¸¿Îá´]Gv©³aÃÚ¹¥ÚÁ…h&¢à¾%Ø´–RH 4 —R§Á¬œèŽ’mÕù¸j›‡Y–ÂÁÒ"évx¯a¦3l¢î¼g<ŽM9T(œ©jæÝΑ¦a¢¬ïùó¡nG×:ŒãyÎl«G¾*{“gaÙµMüÀJeôµ. …¯(Bq8Ð¥ ûÆ$>=”-‹¸Ï“kÀvuÙÜÖ6Líû¡éA ðBhÑô›Ý%Y˜äS‡Jºvn¬ƒ̺½Þ¸Z¹#*kù4Á5fi¨¯ïÚ¬  w€ëXýÞ€|.º/RòWíQ4÷–ùŽ ¢(Œtæ÷õëëù‰®O½áÅ ˆ@mJ€Çì@ ì°×Èn2(X¸ž™ ˆP †ø¸3J ¸W>þ-ø ²Ðä×&&Îõ•&!…._CfªÞ¢z7È(Ç Ù(‘ ÷ãÓeSo ' Õ|ûÑò‹ Tä `ËåØ}Eóîdµ¨wø¥+" ZŒ\GÁÏ…wÌ´ZXÀ´ïJ씎låv}yü}‰-€9¨FªDÄP·ä±Ý¼”ö^Ê"–諞]’ *øä(ªç“Ç_@A7.mîÙëû<³ô×Ó¤v鮡îz«ÿ†“º]á½I³U¦ ól;Tœé÷±b{^ `˜ÌÒüûXº‚V‚]ß!Ço‘6»Ø‚ýoEʆ³0tè€=ËñéÏö’¢£·5¡.ƒäÁ»ý}È;†,wŠÆFåÁ§“´ñmbü‹uö"P€Ý!ý¥áª H( ¾«`Hø¡Úš¤§-¬¶èOž‹´¦vÔ"·`}Œ™tbaøÃ=Ô÷xFzž£âe3ÜÜØ&^.o›È^-Ü‘ÀKŒb¶‡1aì7ƒ[¬MÆnX˜ƒË´ÃûÐE„šC´ÑÕä°‰â…Dæ¤e¡\ØS¤““v‘QÛž[*ù"®ƒåÇšëG ª –éhØñC­mðêÆ@=oMØ2Â0ìÛ-zo»\k–ÎÖ+´*üžáâ•Õ@Ax#xítü:¯+ãXÇAŠ<ÌÅÀýrdT¹ÃUYÔÜ4´Òa5,ÝYº6‡êkuØTÂ%RhÂV ¯’°…¿Iд†ntÜÄ¢Ò$ºïpcÉ ³Ø›çŽV‰ÙE=ˆ‰ÓÉ—Sì%ÌÁð­ð- Nmíü@xW66vn ÷(yZ: AQŽ'¨RrÐù M cBb_\d.ê綃‰ÏÜJä¦íÎ$:¢ÞÁYªPº¯®Ù·èù¤hiÐõBJøûÉ[’jÄQš-¸“²ÓÿíÇŸÞ'ˆ0V¡ÕW*ˆ'ŠlÜÁÁfÏd ¸BÀð‚ R0‹D+Õ ý"°K®çRnìà˜Sc´´PëO…Ø<m&³¹ši–b¨»öÌ­ìÜï­ƒB*£ñ î©‚Xaó>£±y”xˆƒ&¼ã4bì÷tÖ‹ÐÄ$ó8—̲^yÉ$â0¢ PÊÌe×öýÕ ,…I¿n|8.ºWý,Ä3*=<.ƒ®øF`[ñ¶Xx>ÄïÅì‹»pìóšÇ+ïqs8€ ÔŽŽ´aþÓë¤^Aêzu#0VíZªö\§pRû%hö7]?p_>I Ö“Ìò@d„£ŒÌ9:½¶t9 k¥©!öêèç/¤­§4ÆÕ$ÕA-`+îYŒ…dƒ’lßt ½3Á3Ãæ4sŠ-‹Ü_&q‹ ( †uÌÀÇñSõfz#¬B*ahøÞ¦ ¡ó … tŸ>ep™¨e1SØ$ѨÏáüwÅFIÄ(^>“!&†# þ §©”'@|ÍäÐÒ$L!6‹/>%â!xª…‡@Âb´•¢L_¬gú8·„Kê7AÙmJŒµ™ý˜G0ù1à{Å¥µ#7øSCv–¡`°•£^°j‡¢{•°ÖÚf¾±@ïb~Â!‚Úa7 eo®"&J–(…ŠS‹ U˜Û´¶›~OÙP™Éíýˆ+ÃP˜³JiðFð—bd¼‘X1€L*ùÞI¬ØÐÎsÞM¬ÄI~›XÙÇq̨ÇFÑz!ølŵaœ3-¦ßÚ·ÉCˆbü?9ÜhI{_‰ ™D°)1<òæ›aFA<{“pýÉÚþVÞ`_'}n›Sˆ˜ì ¸•¥°´\lDWj¸Ž'ÄPBÓ©ÏÀsa¦Æ®¿oíþI :²^ñ›šüºo…ä P׊ ±ø$àËŸÁw±áÐW™Ô]ˆi=†^ _ ë=ÆdkŒ¾*é1´L!Øv_ÐÄS&hÛ®¹æpãF9AÂ_Âcù䨀Dþì…qzTÁ †ä+ºú#hîx ¥õ|y$=öLw'cñX‘™V$tÐÀùŸ+úWn÷ƒŠªD=6ƒ ÿB¯¦¸\ FO:2µ‰ÑÑYä³±T–0 8®°?´M:€Í/U/ŒúÀüQÀ;­D3v«¥&RaœN9Ø¿µ$œ({Ë.Å`]òI-)Åkó{¨x#ý–„ë?•â½ÖÒd,XKP?·ÓÛƒ[©`<Ù¯æ ¥îÊë×Ê xOK3K<ÎD8›÷­qÎ-Îü+Ù#§®WÒ‰ÖËeöŠ1åÜ Žù €ƒÜK;ð¨P®0Ý$Éó{HƇ7,i‰U ‘`nl%j• ÊüºcýëŽU“  ¸¶E=ÛÆó¹i~ž¨íî?½׺{rÛ¯a~¥˜#“z|ŸšÕc5—êYÈÀ@^%5’'"@ž:#f’-\êƒ>(8_m··¹ÄØ%†! ð*+‘×,ªÌ¦8]¤Ê¶‚-ì gÖ§XiÇ¢?IlªäYÉ|ÎP8üt&3)µˆ‘B~(ŸmÀ²ãòr?a˜o–ò'«Ø—Q³¿ãJÂØ†SäÄAÜpG9Ã<õVÁ}'þ¿Ì>ó£?Øá »jÂL˜õ¢¬µÐ-ÇR%_r°ðå‡â¡§fá’œ@xû‚"±FPò ¿a.Ξö\+‘ò¥T¡ÌzWk'ñ`Z}û†³íýwü,A);ƒ/¬7–»1J„OpSšÄÛ~‚‡®aEɳà/üÑü¹l½â¤`l¶ÄˆYæ}ꆻ‹CO —Å„C³[‡Ǫq;‹ #3aYI²]o%³è±ù L”›l.zè(bÄè0ÇÊWL†/c²H (y‡V‰h3ÊÔ²PÕF>:PÓ¿ ØËÑ ø÷Téà•$Ë¡õ\<7TC u•— (_-VB­­•t™ÉTpËÖ¡Eܰ/ôò‡y[yô…‚ϵó$@X†êX'­Ä_]2ÅÄæG ÌMÆ*Ï®`û?î`i‰$Èã¦OÅøŸ#úÏ‹2t0þiijÍbÀ×€ÛK¶©žôªs «¢PÏ/«ÓNQÍ+ È.Š&eâ(ÿ‰³õ2™©ôÎèt9ì”@²Þ¿Øe* *lWˆYDÖ¬še`Ej= õœm„Ÿc«FÜ|$2&ƒ6;5¶oQF6¹ÊNÐãh Ðú4•Šßr•¦¼ EH%ýYËè{Q¾NÃ<ŸDw÷DR“mÈ g[,Só£-N>v‹¬.Ê;A®‚ÅÅ;JÿN‚`øåTÕnbŒ+8´9/ðöùÚPÏÀ}^+&ˆR{u å_®oþ:܇º¬ Ñ”NŽòu² ó¿ âßߠȯ—è—IM£|ýo1¢ø•ÎOóË3M&/>ejƒë~àíªvìå=cúK e@ÐûÇ’·B^ˆ¹1¢Æ0l:)¬yKâ¿Þ»bÛúAœ»Î •¿ü¼{eæS[dTÿ<ŠNÕqØsnO_Èîbã¥s}ÝÇÈžÄx‚]Má„k… ÌÂ>NÂØÊöìŠççOßüÀûòx endstream endobj 203 0 obj << /Type /ObjStm /N 100 /First 846 /Length 1445 /Filter /FlateDecode >> stream xÚµXÛnÛF}×WÌcóBîîì0$NÜHÑ q¶†h‹¶‰H¤@Qiü÷=#Y®.±)*)g/œ9;sfvwVFRd”'+M oÈhEZI«I‹Ö’öÒ:ÒQÚHf9ŸÈX‡>d£ÃÄ@2Æ[6{ŒY]ZMÖ@‡-Y/­#›€Ã‘K›È9àYC.Ï2ÌŽõä½´0OÖwŠ‚¬ï4üg)$iEØ`\¤è¥Mc Ÿ’ #ƒ¹ä0›’¬ëüg‚8 ià±’%\Ö¶ø¬­ÈDt¢È$°¢ÅeƒŽã‘‰ŒŽ,=i@ 4ÃL“€Ì¶Á>mµÌÙ ; È6É ¬•€ì°ƒ|í"XÙ#*B«ö,Ÿ€ì=:$ –(üǰIkÑ‘8±|‚V„@I˜„jrnÄZÆXž%Ú£Ã-¯Ð_&!~Ëx°t`é ‚V%ŽÚ¥lÎÓˆ%‡$BZˆ30Pè¬%*’ Å0Ó$æež°4µ YAƒ‚¬`.æ„aÆZéˆeŸ½‚£ˆ*×áK|Ì…ˆ´Ã|„! Žâ r„‘#vI H+-l–•l‡€•lgd•5KÌ„$9há— ‘OÖ ÎZdìÉ åŸ)ÿµ9o(C¿ÌWò¯¼îª¦Î^eœéôòåè—ó»’NnÛf1{I夜–u÷âm³¡]M‹Ûr6oh/æÃtí†nW~ë)» åYÑÝõ(?jn.ZÍÊyw?bµÝb{~?½j&ƒÔ7éžµe1½¸þ&ã×Ób6Hy—òáîoò>)î›E7HÝoPu“#¶"[Ö‹éUÙlj;\ÌŠñ ý´“G¤’Ú€hfÅuÕÝØÞúŸ‚â0³IUßÓßLÇò柆é?däïÝ]ÙÒ’B—7U]‰Èi¾UÌfe=®¾e¯WïoÉHwÅ×’péý¬$OWåMӖϨŸ®Ôÿ˜Ãó¥ÎMu»hË9U5}(Ïè¾Yéž6ÓiQ ä•ÔÌÄð9ÉDY­Ú¦èkÑVöúüÙóéÍúxùfæC$ß¶è£oWjïªy×´÷K»‹ë/uóϤßö‘¶¶vvßV·wû!¿ BÑ'ÊϪîR„ONFùù=ˆÎ?bóŽòÓ¦îdÜÔV$Gù§rÞ,ÚëR¦x5õ[9®Š×Í7ºP˜ðÀ É\ŽÑŠŸŒ{]äà7—ýó¯¿ X@ÍW/&“Ë'e ê@Ü¥¨;úäœÓ™G©Ó'§Ê‚ÙÁ;ƒ»$$á²gÈA $EÞj µ.ʜՊQë(TàÈj ý5·Rª^P’»V}· „¸ `Nþ±m®?—] oÎ(?Ç)H–~?H¬ö‚dâ±A2©?H[2 _qu앳Þe Åx¯œÂ¬\¯jÉÌ¢Âì“31eþé oF“¥xåýÐl%ÀÑqJ{qâplœ8öÇiK›ÉºLŠê>9ç°éb?Þ.™<²àukûlóúßþ9–WëöxµÃ©üU]7€ºX>TÄy§H»³ôRn”^\uËñ‡ªþ2Ê_7í¸l—KèËü]þ>?½u)F]Ã<,2y{ÆV1òžÅàABB„Ü+zæ&q%æO±%úÌ)¼»Ød gRB#¯hX¤Œÿ®%ïnš¦ÃbåÃU¸‘Öö§á– Ò‹C¬ï•Ù©Ô#C&¿h告ö T|bWïœÞò}¼ ä1úc{ß™½uêØ½ït?é[2Øû*e6„^9¼·3ëc¯œÁY.?¾ Ýû[·âO¸ûœßçÕÍ«;€WwX²#çœËä´>9V8TxŠ×§Ë§Òï—îÀ2›=*(#\:ÊrƒSÙýý c‰Jò endstream endobj 366 0 obj << /Length 4069 /Filter /FlateDecode >> stream xÚÕ˒ܶñ®¯˜#·¢¡‰ÚåƒìXŽœJÅ%9X>pg(-rEr,­¿>Ý@óf†ûªrYbhô»ÍMVïVÉêûg =¿yýì‹—f•ÅYÊÓÕë·+ÍW©1Óðk»ú5º>t]]]­Eª£º*°a¢M^¹Fû¡ì6WÜD7îwW»™‡ª|[7{×ùͺ½Ý•UÑÆWk%uôÏÙ2:ÊwmíºòíÖu½?äÛ&ïÊ ­›¼I¸¸’šGÅŸeÑvi÷N[¼ÛÕ×Q×>¿úíõpÄ5cq¦è0›Ãµ]P\P÷ ŠaA!ÇaR¿ ± Úá¼Úº±MÙl»¼q¿òfC¯O^¡¡Ö¼­w»>´_Zà˜Œ3) Bå |}eD„¸H2ÂK¢Ü=%W,ê±=a¬ÀÀpXæM¢’î&ïÜHiÂd¿èmÞä×WkX§Þå0•ÑðfWZÂþ×Më,à妠U*zÞ¾ØÝÑvе¯íj[ÚØ€V¸¡ o&›¶³(X‡pàöÂ?µÃܦvmêCé­¸$<_I©¢×7EEãMÑöq[Ø >Y±Uƒ\Ÿ¿¶úÕ.þž†<ØN§†…‹»9É'8ŸV,`ÜÌîU64‘¾ËÛ1ºèñI–ø¥Ü—Àg»;dçxÔÄÊ™dÄ"¶áÄàØ òXÞ> Y¿Þäd8¥»iŠ‚šå¾h]‰ŽO¼'ºd&ÚãZµe†-½XWýZÔÑÓ}²ÃI˜!KöŒ6£ø÷ óæf­´úÄÖ>±EOl!uiæy`OSöÛQ…°Už…)Ò‹Ðå³p½@ëbKS[÷| dtZE[­²–BEßN‡×<ÉMIrÓcÉMGɵ*)Ø¿dkÝPGÛåMWVï\·Ïɪ’ú­ß"„„Cé´&2 ÒØU¹¾šž¹{ÌÖ¶}eå­Ã¶È~MÓsõ¦sý]^½#ƒà:¶eSlº²®€´–ð…–æŸc"ÔŒ‰äIeI_cLÏFû æ‰ø¡¨¶óãZÖ{;c=@[|Ñ‚p.£}î`s¿6‡æû³u¿?Ü M-§ëÁMñ¹-AnLì!ÂNËSw·=wbWÞ/õ;|jw(»×*·´@¹Éw´‡Œ+—itg•þÀE)À†Óæ§ÍÅYÉO¬:—ü4A¢i§áá`¢*þ°=ë ÁìÙ°1aûÔ™e謊4:š~Å µ\Ùº±ån×Ïê\PcÙÛ'zu³-«¼ëw»k»bïö²N‹1¶!öÉ»ŸLÀ HRµ&gð"PxW¾³”Å^GYïÕ =i¤žÍBþQÖ‡öȹ p3©Œ—–›‘(†L 6ö94÷¹e¦Ýë+« ª²-Š`bÕ‡é4½lÊ–~l‹vÓ”·¨ \‡EưM–Ì}9;d‘ -§£¡‘ß’€?É£½õÈ Ë‡ëÛ¼GàÄ/´fMFÿpÃÄmÑååŽæ¶„Æh¬[y@kND*iŠÃÛι0àßIòEõ/õ*3- ºü\ËX$j%â”Ú¹›5 Ll2½ZO& ¦²Œ‘÷Ü»)Î'¨ÿK>p‡! °㩉¹2>Ê^ÀLFTÁ§çñ¸Vk—}Ã’Æ-á™Ó»Ö¼?ôf_t‚äO÷éÌ"$ƒI£ïò!´é'¹UˆÅ¡³¤‹’P Ͱy×äå»›Éd²´0Å“²“LÓ“»ØíM7ƒò>a&áEJ³ÀfŒ œ?÷ш̥÷¤Åqï1ÎCþDì ²¯{XûÈê}gïò4®½-Ч$$ãÐ*]öɬ‘³üÍØ„Á¹P17 ´ª…ìöXPTœ0ðÇ2#ð“c9‘±Ô«É”ç­Ò81æ^±% ú:p8Ëô^;òÅ;–í, kf’8ÕÀ<‰•’n¥7Ó±P„ÑT`-X(飯£%D¬²é yÀD_ãCÛE ­LNQʈëñµ$´5¶Ä…­µ·õÊz8eLx÷ö”§Ùj=™u‚xâ_¦qjÄ”zAïŠw%I]~¼ "AΓO„Ç#6P•¦z–Aë“¡½LR½„¢Aq<^i2ç«ãc­yÆcc‰Mtž@Kd1QÙ…„r¢!tøPöu½mê½k%îa?Í"†I?%AÑ—4µ´>Ù-؉]é^g½_…£ô´¾kÿF‚•e€íìÝI,äI±01S‰4Çwc‡“ô ,v £ :†É(`E¾Œ}B?™´èpaá/„[ghžC­dqªØ½0°k ,§9ºu ÀÁBèU©C¯ês б;‰[ž‰{á–=nùBÜb°h½b8‡åw8˜uE0c.4¶£ß[õ‹‹B?º>ë=läS­»:Å¥é°9Ë‘«‹^T½[¯ÚÑùt°®óA nxzä„ö^•´B;Í“ˆKÀkýhãö>`ì³à—Ö@6þ´ÿ8ƇZNAkT뫚µÐ[jZêÉx°ÍòN0ЙеŒÑ]H—èdp²¾-ÁbÎþâ¼Ø c,u&ã‰qM"¼y󢉵€nÔÞWí¯ÌrøóРɈ°' j[gOÄuAôãŽ9¼#sÂMSä6pìCC—PÁT ðVæóX ×qéF"¶f1È3Ä÷1ÆwФàSíN-딫ÌY¬ÌH™¯`6Þ»oB–Zæ’ê[O&ðÌÖ€N‰è„33!ﯺwf!ƒm´<ɰ:–³]ôø,¯=ûîõ³÷ÏeÁŠ@%”Œuš®6ûg¿þ–¬¶0øÃ*‰ÄìÔ=’@3Ül·úåÙOÇ7¯`Ý@°•«I~ÚíD(©à\¦GiO΀00_t ×„.A®Ïb ¡Ï£‚Ä ™ÔXóšÎr`MÍ,à^›³ShàBðoh@/ôí£àƒ¥€¦Kò©ä3a»Èúq«`tDo£‚éœíð+0Lîî('Ë£¶ÞÓ ù›„¥ýèÀµn1±’SvûjzÞ-M;º=•E}=Fæ×÷ʰôªïa/M­Ôc=ô€£õ°ŒÊCÜå§Øi©óø¨ä¿¥æS¼ËvnÓÎgm²X€i÷DççÐ.©d Ò6ê^1ÿ˜¶1çÓ6fAºß+cLÛÈ©gc|ù8C?¦%¤—µÍÚ˜§ÊÚ<5ù“¡‘}4γ<æ!.ÒçÆ÷édéCõVÉ’=¹‰%ÿ—\…à©ÍyxúíF†œ¹(ÎN$L²Ø¤ê!yŸ™îô¥Åy °·Ÿ;ÁŽšžV‡?ïðJ,˜>a,Õ,bŒ”?á Œ­ž[@.ûÔÔILC q¿›ø?@4²D•Xèkð¾¬iØå BŒ”×YŒwk:rÎÂG×7ÉT 9/+À;îCã½|¦–ïTªç_ÓšÒÞ‘…Ha(/¥ ÒÛÛÆ^§,÷TJáîd±X´hÊ~žËzÅ"2æzp`öð¢x“!ãšK1Êó‘¡ã²l0¦1ŸçÎQ±…N¤Zà!O®uйF Ú¦4¨YÁô –œ=ð>$Á*5÷:ñ>dz9øòéh7¹ Ò;1À‚®ë%Ó£?Ê¢`I3Ënð=j÷³®Ú²¥‚øä@ÆÒ©-Ù‡=>*ÁÑeðÀN¦I2ÞÃã„F³±†³ª÷%VdàõÊ"ª4Öl€´=f)§zAt§/‡\jL .ÙgéUˆIîŹrƒÇ·G@ô¤“I:NÒì˜rÓäÓÛgqaö~ÍDß9Ê5wD»Õ®PZÓt³›)µ¥ b™éÕ€¤«}éWZH1VZHÙ«vIÅd²×úr^„!ƒuÛZF¯*Z)ߨ¢3P¨l^UZȳ•€cîEœ2äÛj‘EÈÁûlŽ 9×BñØd3‹uYýó,N”¹¤Å%Ð…Uª¤HÅÂ,T¼þN^­XlØhýXPñ`Šm,ì‰áË€Yó”ŸÊ³@Œ”êQcÖ˜T'ÀJgB,™Š^aÑ­¤JîËö#GÚî]m/Ö°q%%¶yæm†dÀ%õHx]”J4ÍÛ0B^ŽÙI”ó²j{íå#æÛm‰‰J[Ù+g™$©À›LÅì^ñ‚q‘<ã5Ñcô­¾¬nÓÑN>Ð>%â³›†¥6”Õɬ¢àBqØó÷œ*MžŽJÚ®bVc¨‡¾PÀ³H€ú™ø\‰cñ òÆ‹ñ¾(†åÁt.óðîBÔþfEE¸·vy:ÒïEµ)l¹1^˜f©­°ðÄt,ð”Ùi¹_­WG Ý?øÌéY÷d¦ùc%/ÕZO澺nOà×dÞ5º7ÑïÅÆ]×ÚòYg˜3ß0g¯$‹š¢¯Ê&ÛŽÛ‰î&T4'/¦ÀÐÍŠ ÔJ0‡µtÝu¦VB`î!»Lx[&l áÅãCë, ÝŽÌ$Ñg”0õÀ¾Ël–x^ZD½GÜ‹=_t¡©€$lš‹……X€ñ2x%É–0žq&ÔiÆ"Ÿ^f< :Îjæ‡iœû…¹'c¼ÅLãcSb†’›EØ££O#S¢ùÒì22Aø'@eçŽR¡ªz¡y¬l1Ÿˆ…ÔªêMl’ì |cÂ`¨ªÇkWU~JâRÉbï›V>€*Ãm~å e˜N 4N}Ú P¥ÝÍ„ˆ“Œ¯4Ydþ5•‚dXªfճצ€Xòƒ~ˆÑCáÑ_éùò ¿­ÄO±ùx¼ ±ã˜ýÎ_È÷4ü ÿ}\Â^Ï M°Þ.Žô›½´Oýíðî¦h)Ð|(O T=­oëýí¡³5O‰Ž¾o®À/ÏooÊýŒ^áÿ(«My»³´H4]—%®`8ß`ñ24ŠRX*cŇ}èí¶lëjMC£uVë XŸ„í?ˆ¢ÝYgÿ` €±,K|Š÷Ï™YîeX̳؀hÚUÍœUþ¥£Ÿ endstream endobj 377 0 obj << /Length 3936 /Filter /FlateDecode >> stream xÚÕZ[“ëÄ~?¿ÂOA®¬…f4£ o8—¤l*I²=k‹•%—$³g!ü÷ômt±µ‡SP¤*/ëQ«5ÓÓÓ—¯{6ZVÑêÓW‘üþåþÕû¯³Uæ‰NV÷«, scVI‡*Ê~õmðMYïÜz'&è4°Áy½ÑYДõ~úõ÷÷Ÿ¿ÿZ©ÉDi*•À"4Åß™cºRféðþ»ÈF “ÄÀc=O;GÚ<Ì¡X¸r­‚އÿìôGüãÞð^vë š’¶e]ô%ðЋæ?’͚ࡹ´ò Γ}ÛTL˜ë¡»jªG5í.-¯ÉÜ.é'÷¢Úb•„Y¤ýž:a‰Vp.iœ!‹ “tµQ¡É-3•·ŠÙ­Â,¶(4‰b¾ªt¨•8 ÊšYÎXÝê^q§—ªâ'PÊ­´*ÊCcs/íyAZF*fqÍ‹â&a¥« Oß,­¦CeìoZ,0é0SƒÈŽo¥ÙÌNÅ ×câàõ:‹ƒK ZkOMëîXweÏzhªªA>u^»EÏ,i÷™ÉÅw‘Jj'àSJ[Xží‚í WöŽŠÑyð·¦wþËBæ*Þi†%°Ùöï7*5?Åcѱe G`/Ãé6Nò0Éã¹nñ8L㯠ªg~àP`"-ÊÅã¡ÇNÜ:¥(°`¼1L­Òwsìù¦`«/XïwQÝxj=DÖû6¡™9Û’¸0›ýŸËªÿdUï"+8ø{½_Z§`Ãê·ˆ=O€±J¯"UbupDïºt"ÂÓщ1?#½¹°Íº=:>’ 1bˆ&µ³‡ècmðƒÛyÞÇj£cÆéÜYN͘? x)μÊÌý sÿǪà±FÃ×òYwlÚ^>(Á%™Yy‚l"0Ž)©M_Ö®<¶¼d{lx@auÿ” „NYhpp¦=•Q!ÑÛT¡àHèØàÀ˜KãÁÁ7`Y–ó7&ÔÀª´ î×¹Œk¤–!‰éºÛÓÇ…³0ö“ÜczâO³ÙùuLÀãø‰Ô¿=¥¬5ë  Ùì¹í>€‰ èº<+'›É§¡-‹C“ ¡­*¶k 0§ZXk‚Æsâáç fGì&ÖIhGüw*ëòŒ3·0µÑašÆžüÀ‚"ï!UË~ ?¸ÙðkÐSÑ–…$5Ñ߃°]ç>XІ©Éç§ß—}µ$žŸÑS¬ 4EuQš¯<ê$Ô€hÑI†éø¹è®p)­Å´³‚.=FE!(P:Ä¡¹ŽÁ‚Œޤû¡ãkÞ,Dˆp&^Ø Ì|<ÎUñ ð·l%ýê4 5˜ÅL‘Oå68HŽ"öÁïŒ\k¥ Õ,üµÔ,÷ìΩ÷Ü®|¤!âñ˜®”@Àð`W•;$?NÉiÐõG&àhÀ6Qø¢XÔnaÞܸƂ}Äa¤FrÞ$øð¹¬Xv¼Vˆ±â˜™øØ••{èOM'ÌÛ¢sYÉ6óLÏ•|Æ YX:×íEú#.‰#B¥8àhꄊ‹ú€ ”ß2È”—)½$ñtòÝ$:½' @Ä/’úª¨˜†6K> ¶/wëª<Ô¾’bcؤë>\ŠÉ²ÏóåÌôTÖ{Æêü p˜wU´ÛÚ“DŽx’3ñAÀ¹ñFìZ¦Yô\8ßFÜÉ·;N9{·`ª"Û‡K!5 £Ü,E¾ÅÀ¥jf9¨Xo6òž!þîKî1lÌŸ·Æê¶…"˜^ü#žÆ=ÍóìP¸g° ˜Gˆ“‘?®ÖËrâÂÄ%¤39ŽÐ©'Üt™‹wôUVØ&IC¨2çû'Ù|âÊ&'wDaA ò|_ð)‚ò5È5n£³ùT(I‹~„_ÏCR0àï¾-2祟­8s&Æ »lg)ˆòwÞ()Æ&wÕeï8þí®B#—Å Œ5ë9é¤_•; ~0Ò˜ºsN2Bi|Xæ&ÖhÁÝË!–1ª8Ê9i£fU´˜²-Ô]*~W<>yy g÷TzeLŸy¹s €Ó¼Šà#µj± ‹ƒ¯?}µú–X nÐJI—ÆÁgç!ï¢ä—¾ÁžÑŽQnì\;²'åmó*]ã9Šž¿+{i0Eïì\q‚Þt®¤'”«)zƒgQCö‘Ÿ(¬OÙ9îâ…D¹ët—B¾Sz„IÏOoõ \ÉP¤w®Gð%âQš® Ñ[c‚PAE×ëùÕÞmž¨pÄÇ£Gø0X\e¢sáûD: 25l„ÉÒˆÀ¸‘œ .BWî]7@ñœa ¾ðg†cê#ÂWììíp¶Hgwm †{dÞaf¶Oògü쟬¨ÀÌ÷ò5É3ýJе†ÊBÞ¡]%Š6¦d2ê j³hYª«®q]º¡:N"ÎkÄ4‚ä„]@ ˆ:ž²ÊSI;ƒQÁ|UÓó36¼QÔ^‚%éõG„è”O°K¢Ú¥í–öÙÔN¶l.\pÔ.\2Ó¥ÐB5Ø-œ_ÊìËpžp¼–¢TA+ê‚04R=†Æ£ÛÿÌí!¨a6N±ÜþaÆN¶½+‹Š)\ifT™Ól¢¤ñ+-ÑqÏTJ¡K•oœCv¸eŸP3)ÎÀJ†‹`+RŒñOøƒƒéŽþFk¹­Ê¼Ö(À5íBubDCüýj1/cÝ];IÆ—1¨­lý QÕ´R)wåOÎÍC•‘r³J ééåÏP[b^__”IMl†ÔªLJ]»™ö†´¿µÆ¡ìí¨uñ\9Œe”d^.€ÿM)à¬Ö -¯s:Ç”áF©_Þö:ñþÏf+(- àŸ–)ó†')DÅ‘éžä±¡-Ò•‘¶ä'ݬ&ämüHŸ(‡”šë\¤Tî€ÖK¤£(“‹¤¦Œ õ¤Ã¢bs*Ýv)qªiƒ‚.2q¾NÔšãÍ»HS8ú5¤ˆ]¥0¶Wqd#N’ÒH]kà@kŽ Ÿ)Y—?ùˆrQºñ^é¯.ð}Á?uSo°]Pˆt5U ÷¢~‚|ðôÕǯïxÔy€¶^©gEuð‰jwRc{ôxpµk ”!•Z¶Ï½ZèQØ›ö- ‹•¶¦P‡¯No„£2Ç’>M"‚Å`0G™ÏÔ ÅØŠðÜiã!ºc§õÎÏÄO¼÷ÖV´gÐvj­8!/|c2Ö†ÉÈ,çì±sùè›WÔ"+»fÒÿ^ VžPa£€¨}6£ò †ßš·€TCϤý¹uû_~~ùCxþÂÃ_}±ÃâIPûn£­G20èžO“?vìˆL’u<&¿r‚­p\Ú± B3Mƒ«Ð8-bã¥BÜL$ö%8hQ‰dçȈEÎá2+rDäfÁ bü7‰ñRé×Ì@‡q4iqs¥¦õm2^¶oÙ˜‰X:¶]S]ú¡[…j“:ìat®/ê{'»Š~·A}Û¶ßÿ¬îÔ]ô6»zvUÕ<ývÓÂÂDÚÏÐTr38;=ÔŽ’rn—ò¤Mè®S ~—<©_È“ö:OÚÕ„<äÉŽ‘ر…iï±%¶`\{¡)€!ç~O8…BäòfTž†I”ü»1³Ý°ta@…Ö#¹ì;®Mdžk.}gÜ€÷\‰å9aæÿ‹hîda–š©‹õCM÷¸˜mJâÎÿ§ˆ°IC>C8À“T™Ð|²×Є塦*8 V[±˜=–CÓ8X‡ úлGjGa°¡¥b'†õ†ÐôqCÀ"[MÁQòkøÛPcËÕ¥[¯æ¯?¦Š[@óY˜˜üS9±ðMQ2¹ÅH®Qý‹=öîF™IŸ®n€2@&cÄaRv,ô°rxUð äu”QAlðù¤†Æ–À^Ž÷ew® _Ä6´%h?—œà¡¬k)ΰ¢¸Ý1e=ãï†`à/(`è/(•Ù[)ˆÍUØ6Z0 ›…Q2 è¯×`Yé1|I÷¸Ô­½ça2_;xo1 Óy].VÙQ˜e溸“YV˜ï÷Í”àõý¯ÈºΣMº¶ed¢l긹¿ÁÑІ¡’¦’ÿÃÏ'^›ÇS1ˆˆ½903uûÝË><Ä"M=~îà˜›œ0Mè$ ÚK§rÒR†H‡œ¾bĸîáÒÊtu5ÎJMºRÉéK0â2¸~d.j´N¹;·ãã¦ÉüÛ¶¹lKËÇýf±Éè‹$ÌÜßøyÐ6²0~á‚ÿáB¤åe}”Ôåpõ*ÑXˆ6 VzÁÐn¢üÅÅž)r¹Ý;0T‚Å6 >…èý(}ôÜ¢M€±‘%ÇGG¨¢;'OŸçbòȸ~ù¼¿hàÀkdÛCûÅ]EÚ$:z¤¼Áè*Þx˧ RòxæSL†Í´‚.d|Ö†0  òHÚè8¨g ¹º#f_)ñ#[qÇ[`ðЌլJ<¶?ùœ- ípÎ㥇VPEÙ 4%a Ÿñ|rÿê¿”æ1 endstream endobj 383 0 obj << /Length 2154 /Filter /FlateDecode >> stream xÚXYä6~ï_aÌ˺€nùÊ[É4zlz‘v;yP»TUÎøŠ%g¦ÿýò’ëèê /e‰¤DŠ"?Rû îobù~xºyÿ± ê¨.Ò"xÚUÕJE™EI ”mð¿ðß3lîR‡|ËÐð¬ûiqÆòÌœÕá3|ªp\†m;ì™÷LËÆ ü|c¡Ý83Kógj7 l3îd_óÍÝÂ0¯ÂÖ1i6]ëÕ‚i Íµ@{‘…éA0ض½l;–ÜA»ÍoOŸ‚»DÑiï’$ªs9íO4nî2•…Ó<âæ¶[c£Í*UøëØûY”Pá¾{™ÀðƒLõlxe§ç½™y ê?2­?'™?ÇIÑ´º{Ç´£·H(B=l™£­|ù3»tŽUºèo-'–“ä|’‹‹ÈTåIx*:cK‰ãFaÕµûù]ÃÅB?ß]G÷ùuÝN£öËlÐøœOøý;fÉAj"Þ Ñº¶Á¾ðt\ËàÅ“E¬«÷c·5bÀl§‡}g®øsœÇ¼*ËON"#Tï Ho=8/<¦h¯B¿Ÿ¶,¤(´êò1Ãã%‚5 Ó´»wãtË#tÈË;³Cªð‹å9{„×_9­ì–ù397öß¡àšÝþûãÓÍ7 ã ª,*‹:€Ø‰T]Móþ¡O‚Æ›½†ƒ2 r•DYUŸBJø3zá‰ù&®š[3`«4çÈÄ£Ó²˜Gíq¼ž™©>x,3[Ëä¦k'Áœ-xL©Ê¯c¹^£/<9hÊÖ #R0¨q3PB ñ`ÎuþãoeÏÑÑkðdábW¦æØÀ ýðá”ùÏ;ætb$9("]gÀ# Ÿè>‹,'öæh[G$…HôÜ™žù á ’XÓ Qê+ÝrV'!y±²±›õ`y{ d$â~ƒ{ÂDÏÏc5­û8oà¹k^#é¹Å]iY êÀ±§&%-«5Ïĸ¤œîpYnޤ¿T<Îí¾twÔŠE¦ª«ÎDn¯ÄßÄ’'P A‘÷7ò²€Ê'ARVQY—’—éÛy™¥u”Æò˜©bÌ9Êù¯ÆOb•âº=K?¢sà`BÈጠ8qa4Â!ó"üXTÎm͉š<ÜÏã2 ýˆkÛ 2”ÓtW¤QNЈîÈë¾âlÚ›ÒçýGð³Rô¦eTUâ eÖ døC¯1ë³’­/Òðw x8å}N}Šêª(¤£¥–×rY‡ê'¦Œ™1ch´e†Çrµl¬O6O2l¨*P»ÃF3¢{]„-ùÊœ¼|Îü‚Vò²Cg¢F¬u¥o«,’(­Ž§MžÐú+GÏÒ(†š ¢=÷T 0„…¢!TgˆOø³ t± ÀŠVåk`,¤ÐOÆiu-k E°ÔïéŽ[ìf㨈"Ɉ¢óè4a]–,'Ç¡3ÿÝT^î$g£e}+ ý›(©€È'Ç`®(>r˜<Ê6PÀ¯…(µ.IIj–à~Ó<²bGMèe* [˜Þ-ÐvL;â8ÏëR4ÈÆµÂ(:'íë²ÈÓ©Ð0ÜIsëÌ-éõ—@YR±«OŒç›0c—#úv׼Ѻ¿,v˜Ti%Ù•VX_f#´Ý24N:và0|W97 ô@§°ß!¢Åph¿x•†4í1Æ8•iÅÀ¬½̬;ÄüZ½ZªÂO?ÞË&¤ãöí;5Ëx„|Ú)“¶nmvóØK8ˆ B¡¼ô¼}Û[ïY|Ú3á¬t‹¹_¢ïÀ_ÍŸn´¶3V˜Ï­ë1 pŒµ”ÚRÛ…sN–Šôã?ïoytÿðQFt®8 ? Sï>bÚ Óq÷ûF!VÔaÍVÔø;}»aà·\×ýÎ4·ñ˜-EÁΉ`æ ’u)9Þ||HA üôx/Ý8øèôÄJ½Ñ@–çFõªù½²pFoö™žUzö/%žb ¼ñ2i© ÆÒNXžP7 ßž×ßRl¯»Î̦í•S @#è¡€ûDËÄ¢qò•'Ý–[X¾dÐ%\v®§þRiUV8¿9µ’kG+\-ý1ýó”*YÐb?ÅzZ¶µB[_÷Y]GyuÙ’PrzÖÎ |¼n²(M׿aËÍ/µNø*j39F;ÈB&J4G‚ô)ùàùî+)¤û‚dþïDþýÁPF*×Ú"|üá#8’¥ä>P©“p&tv44Å<çX„ 0œ¹Øi‚´mZ*’ÉÝoZ7RžçT!é+I}ôtݸŸõtÊÃü¬Q¨ÀÚ_¹êsÃ|"öH¡fmæ=L¼k÷œy”©µ“¤,Pert¡»Ò|B·Z¯¡HÀQt4ߨ0ãJJDœ6ÑñÐ@D¹JÎ]RÞQܪD½>A¢Ž¡qWTEø=@*‡àé±çÜlñ%ƒ7†ÒÍ8Ñ8&'þy«{yxLä:ÚðYþ[Ø@â.Á"¿|{!®àƒD|³Hßìèï;|.øÁ@1ó’̬”‡æ²s0z­Éø‡™‰ýÙ¬²­¼=/ÝH ‡~Z¸[œA—Q‘”Á]^Eq©øI|&¯Òÿü)¾@ endstream endobj 379 0 obj << /Type /XObject /Subtype /Form /FormType 1 /PTEX.FileName (./figs/fontbbox.pdf) /PTEX.PageNumber 1 /PTEX.InfoDict 385 0 R /BBox [133.702 216.819 267.958 271.893] /Resources << /ProcSet [ /PDF /Text ] /Font << /F15 388 0 R /F16 391 0 R >> /ExtGState << /alpha1000 << /CA 1 /ca 1 >> >>/ColorSpace << /PCS [/Pattern/DeviceRGB] >>/Pattern << /Pat101 392 0 R /Pat102 393 0 R >>>> /Length 206 /Filter /FlateDecode >> stream xÚmPMKCA ¼çWÌÑ ¦›ýÊî±-ô&îM<)m)¯ ½”þ{³Ï>+Rv“Éd’Á{ú‚㈉½%8·$)s‡Pq¸")qP|ŒÖPn!—®vØÜÓ³Í0u;‚ÿÂï‡ßR¿-uؒÊ®ðƒæÊ5«UiÙhþ$ >²´‘UÇ íƒ^ï³7´ugå¿, s.¦6’VÃùs÷Cœæ=¶qÑÉ óÀV¬ÎVUá\C÷`BDÙIÿŸÏÊšÊ-äÒÕ=x1åo×™J endstream endobj 392 0 obj << /Type /Pattern /PatternType 1 /PaintType 2 /TilingType 2 /BBox [ 0 0 100 4] /XStep 99 /YStep 4 /Resources << >> /Matrix [ 0.5 -0.866025 0.866025 0.5 0 0] /Length 21 /Filter /FlateDecode >> stream xÚ3P0P04b…¢T…4.U endstream endobj 393 0 obj << /Type /Pattern /PatternType 1 /PaintType 2 /TilingType 2 /BBox [ 0 0 100 4] /XStep 99 /YStep 4 /Resources << >> /Matrix [ 0.866025 0.5 -0.5 0.866025 0 0] /Length 21 /Filter /FlateDecode >> stream xÚ3P0P04b…¢T…4.U endstream endobj 380 0 obj << /Type /XObject /Subtype /Form /FormType 1 /PTEX.FileName (./figs/fontbbox2.pdf) /PTEX.PageNumber 1 /PTEX.InfoDict 396 0 R /BBox [134.454 170.337 300.941 303.869] /Resources << /ProcSet [ /PDF /Text ] /Font << /F15 398 0 R /F16 400 0 R >> /ExtGState << /alpha1000 << /CA 1 /ca 1 >> >>/ColorSpace << /PCS [/Pattern/DeviceRGB] >>/Pattern << /Pat101 401 0 R /Pat102 402 0 R >>>> /Length 240 /Filter /FlateDecode >> stream xÚPMKA ½çWä¨BÇd’™Ì+h¡7qoâ©Ò–² Ö‹øïÍ~¹Rz™äå½dò·ñg¤ øìoQAÂÏpŽA£`d ™»)b6l!j Uê5dRµpÄý<3¬š‰zIˆq5¿¶Œõ®C¯úoO @¸^Y®¡úð] Ü?q¨ÁŠ16{'› 6ïðz³¾}ÃfÛ³ò_–‡9ï66í÷Çq$Îó›i‡Ñ'·G\’…ü«¹ööLW7÷r3L|r™U½=/…Üe7ƒBóΗHû/dìüØî`ÿ endstream endobj 401 0 obj << /Type /Pattern /PatternType 1 /PaintType 2 /TilingType 2 /BBox [ 0 0 100 4] /XStep 99 /YStep 4 /Resources << >> /Matrix [ 0.5 -0.866025 0.866025 0.5 0 0] /Length 21 /Filter /FlateDecode >> stream xÚ3P0P04b…¢T…4.U endstream endobj 402 0 obj << /Type /Pattern /PatternType 1 /PaintType 2 /TilingType 2 /BBox [ 0 0 100 4] /XStep 99 /YStep 4 /Resources << >> /Matrix [ 0.866025 0.5 -0.5 0.866025 0 0] /Length 21 /Filter /FlateDecode >> stream xÚ3P0P04b…¢T…4.U endstream endobj 406 0 obj << /Length 3244 /Filter /FlateDecode >> stream xÚZY“ܶ~÷¯ØèEܪ]š÷¡7Ù±TŽ+vÊ’+•Šò€%13ÈrÈ1AJÚT~|ú¯áʱ_v@ qt£ûëÜo‚›·_òûÍû¯¾~e7aè—iݼ?ÜäÑM–Ç~˜g7ïë›z‰ŸÜÞ‡a”zoûn¼ÜÞÇyêu·÷Yäý[Wƒ½ý×û¿|ý¦¸)ý2ƒ¥`‰àæ>,ü¸äÜ´¸¤ii&Ó¨GõIàU½Vƒ®¹÷á6ʽ'n[ݹiL§ÚÛ¨pc-Ò·¡wÆ,a½Ðëe¿Ã³û¶5¯7Z^ú†“f^¢rÁL'~™¤À”ps›†rtÅv¡£;Œ-œºkyéCßqÂÍ}œ¥~Q¤ !9ïïæ~–nÁïj3\ïE~–„Žæ¬I:£{Ÿ”±÷þ„ÂMïWR‚[€Q2t’PÒI(ÐÇÀó&%‰(O —ûˆd¥Æ<.¾S£Íí…¨Ý)n‹ØëxôÜѵ9ôø¥]é±\¢Ƚ6Úž´&¬HR ÜW¿:\îšKDUÁaµKîÐYF7¾c"4ãFò;¬VÃb¨”’È!¢¶€»qîL¿Ý(âE5ð&½[Ÿ…€¬p¨[,!°@¡Îzнùc à”a .@z}7ùGøf5„Þ c+¬Û5]ü†î쌵9,TáÈ4õZ±v' ϼ¿Ÿ4°Ù?¸CAˆÈ‹ öÚÁžŽãXUé YP,U>'Ö™ÔÕGcÍ|àv‚PĽ!¬ÐÂr¯¯ ϘÒÈõHw,”ªu!|Ð9î÷´w7sÐ(hnÑF;ð—&Α¡@‡âŸ‹2=·8zÌq?F)XÓ’jZ DSR¦5ˆíGžg;·#¯ṖiôG´üñ!ŒûB΋@çÞ²ç²üøübgÄbH—‚BîkÝ#ZàüPÒ‚È%Z(²eŠYwe ë¬|8E•OÖÎhVÄ$žAYŽ@][L$:휾 òÖ£ª¦é( P!ó™maèÍÃ8hë*’™äZÅq^U‘ëD¬è>ŸG†×´k–Î`F`›8øNÁ&ô½jm#y *Àl’TæŒE÷)h€³]ê§B¶Sè˜fìx£çNÐwmÿe4@Ñ ½*¼…“CÚZ»[®í38*>f µ‡ÍµlîVBìvK5AO~æ¹ øþ€ëfEYy- C ¯yÍäEl=Iø/x@6/éñ0Ø÷„dàueiçùP#èTw¸KDDÓ,ªqèÎj0¨äÕÆ^ʼn©ÇØÝÉFšOtzþVP'p», A´H¢Â;; ûðëA$?¢Ñ…s¤‹Cv¼ N÷ÌÝ,3›?—G†%dsÎÂeÿ,ù깋!•bYü$¡¿F‚oÀ¿oÆ¿?ýòãŸ_ì6I%—HŽùBpû¬¸aäwèøwÒv$X„‰2ïÇnÐn5l¶rÒ;ŠaÒV[…¥•í^ìÅ~0eøh§WÑ$äìy0åìöÔ¹DFŽK¿#Å}¬zs$ÁM?OʱŽÃeþô¬uüUõhªes!¥Œ¶&"ãà¸yeTÃc¤7Ä|?p„ò¥¨v-"\è-¡V9¥Òº?¨ ¯ ‹( yÚœjäÜ»”Œz(úW=(ìã삹M— æ´ÜäãAÃ¥Œ“£‹*C—”à¥ÏBdd–Õ\ÒèI@R€µX÷sgÃµŠŽ$œ—äh3 ¬V™¾ü’íÀž*×¶¿ŽÀ8¹`¾Ã•?Oä]¿çË«¾³V[ôÛ>ÇEÿ ûñ$RÀ† õñ+aÛd#0€> !ä¤LdOŠ/=v؇:¨¸FÐ"òA·ÝjÀçãNI€°œ hÆ;e¸Â/ó eÑܰX¡w+ü0,%§ÏxØ®%ß]r… Oûdù›}E¯’9ü¦¼mf"Ͻƒ%¹L';<Ãa쿇Á×8Œ?(§*#[{”<öËpS4e@Žc‰îjÍê8EhSÊ ë$¼/èÖ=kÊÖ­O\s,²Ùôâ‚_ˆ³4÷+þA F N WHÄæaôròªÚ£ÌçB/40káÕñ&ÛeVïLQ Õ`»’øL¢Ô{àŽÊªH£§’s«¹ø¢ïÆãéw‰9ûÃb†ýf¾c—8¬fá¡ï\¥\Š]£c‚3_É +B®œÞõF|«¢ÔKáF`++…™ü©’“rø¬$ǽÍ9á6^Jíivs‚™­$7rQÐÂü¬_Ô?N2WoŒ#H‘ª«6¾k—E÷j‡QèQÈ~j5§Ç”ÍÉv鵦’´û€>öÚ® Ñôº$~šîJ\çpî,’ Pˆäǃ¨œÓüs'.jË¡„[àq¨òl¢á„íLßÙðë÷5|á{‘Ê4ñó<Ú”jØ_cZCâAiiJD¦ÈQì} Ö¢(pƒÑ…ð2N¯°Wòä€ô…"…”ëõØ·x”@0å4ñ¬Ž­—Oðæ¬)0HJžI} ¾çü ¿´²Ò"q`ÂÖ˜c»gð×o/RYäG“‚óB)¯(VíꂎR4RœTHºõ»RÍÈÒŸ^ºÎZ÷x=8×0Ýèbeì$ZNÙCRîÑÕç`?åzó›Â“däªć쮪q—A!¸”^I6-Ý&'¢­YiØF%Sæ° ú%0Åv«åÐæ½»íŽG—.î³G~«Œºì㸻ǀþdÜ"f[Ä=›ºvƒ®|K‰æ´“+ëÚ €»gU¶é¯ÂNÈÝr? !¦¤žâ¨pÏ~÷þ«ÿ›kr] endstream endobj 410 0 obj << /Length 3360 /Filter /FlateDecode >> stream xÚ­ZYãÆ~ß_!ä%`Äí‹—ßœÀcläÚÉÛ©GbL‘2Iíìþñ©êªn6)Í"ò2jVßu~U=bs؈ͷïÿþîñÝû‡rS¥U®òÍãó¦ÌÓʘM^èT@Ùo¾Kþy´ýt§ÊÄw[cò¤ï,6²¤¦ßéh©gìêó¹éD>õw[˜¶·#}7#²]ýÔÚý=|:yÅ¥û yiÚ–—²¼IMßm3M-“vC?òZ­‡Å! ÷2Œýp÷Ãã6[iÜ…¶R¦UÆ:»Sõc35}—â“<ñpZë„~ -‡„Ñîún_¯D‡ÕïdƒdB›¼PUÄB™—©È ð×möÐ|/¤¡q1§e–ÊÜJ©¿Øû ]b¿J‹¼Üè4—|j}½F™–U±ÙFƒx7wîS=ü¸¾ËâêD }§þ2ZïyáÄ馨=îù¬pÇÓLáI¶²2iYV›­*à·¤ÓÀMReÉ·Cƒ Ù¬!ל°L™jXÅͦ9&/Wsb¯µ(<~e:±õøŠ-¸xÏ”Ïç¶nPØ¥0ɇ‰zÇætn_iÄÉÖÝÈ“Ž àzò–{†,)f."Éo=ô—nÌ¿;®á´‘»ÐFT`;ÂnZ‰ä@|‚KªéÐ:&§¥Â³ñª{$",ô…Þ—c?rÿŽ ³öMWOv=çÙƒE-ˆxBÚ¥šsë' ùã/ßo%N ÎDÒ ‡¯ö96?ÛkQê<•YéGßÃŒR©U‰cõ½›æˆËÁeêŽO¤©ô1Ú‰ ÷’ž‡a=®ðùzÈ ƒÎÀê`ÐA¯O¯²ÔíÇ ÚvRËMòï»R;‡{kܘÜ)Qj¾†»Rßì˜ü<ô§Å€p#Çv¤<ŽÍSË“<“…cò˜²,Ê4ÓÅ’‹Þî/]3±Ÿ Ú_œO§q74ç‰:Yë#¥â÷" {’?^{1™©_&Œ¢]¿¾f“ÏÁq̃ݱ38s†tiøÈߺÙDäÑö»º… Â,bͪR¡‚>Ýž©Égáeòž–$M+œ¦Ág`ýéR·ìZ{"É÷…¢–ŽîØ™v$Z†E*+µƬ"yÆ zü‘ÎAµáËm™C„<:%~aê‘»Y`ÀµÄ€ø„¯4t´­ÝM.^GKäÉó¥Û9ßvm ª‹Ìƒ²G*‹äSCzxÅṲ̈E&°Zón×ë™jŒí}¹^q ¦æ”`ÁÓu÷¼¤„‚~õ‰[áZ$¹ËÐù˜?±èÀp5›ÂÁÅ‹±Np«|Sä~+k ~óót+Ö•o‡:„X·x]¦•¨ |f–%ÿeY að6°‚#6HéhÔ~p^ï…4 >9Í´;‡¢N¥ÀP¬,ãT:;5;çK5Juð~“¬±‚cÖûöË4õ$ÕŠìˆt﫱{ÄJ– '…þˆ‘§n©™9qã+ŒðûóÎiG䯑!è‹å}8ú\Q–&¹g}ëaùà;Œv7£´UD'_r Ü:UûRÞšUvÐtª€} èë!46HJø§F·÷ÊÝ(S²ZMàÈR{†.¸´?7PØ£(ÏN¼c^Ý<Ñ‘Éå×èØõκLîáã{ˆÐ1ZýMŠ2*Ù ‘±¸¯}3NuçBmáîzIòÚuw° ]ƒçÄåì4ÝF±ðÒBë.ð¾Uî÷½ËTrÃS–:sRð锬n/|Ȧ#žèJ¤…YA"â¬(’ó`ŸQ¥ÝÕnX·ýGçɇg"¾¢p]´’L­éçØŽÔÃwDáI5§i8ˆÒ4luÖ±†;sÊÔ-¯q]`ÞÈ;u<Åû[ í/ósm1‘ó@¡Â´½óèŒÄA`ý¹õwj»e†S¶Ðør§q¿;žLç‚ÆsÏK¤ÀëgÕÜwµ*ñž—§V¤^4ãÆµj2ìO( KÉ%ĪSíë:Àã²øá³m~ô˜¼…æx5Я¹áÖ0/òl.#¬9æÍrE …¹î|9o©…jì?tÞÇO ´Üœß¬g•ÈÊÆ´=^Eøž4 Þ?hv7¥·­¼o]M^ÀH@éeÐ9Š¥cFJI>zµ¯‡¾s`û¢8‡r/KH•ȯ =¹UÑ¢Q’ÔìUx‡Q„ÀM?ØÕÎȦ£°QBµÁÿ³,!‹ÒK¡zˆ¹k†]ëE"ˆmÛæ<ÒŠ8W,hE¦~ 5Þ€öñ&—¶¼„wã:da¥áF}¢Ô›²V k— Må!:‚°):6_wV¥…ªò6’õ‘(‰ÞÆU¤$au#C ʰZolÐ<ÏNTÔï® ¢ÂL¦È"šÁÛFK3”›A>ܤ¥Z•Ôj/›köÿ ¶òÚ X8ÖŒ)¾ÄØ—YRlÐÿ>¡¡Œò&gûÎm·Z†DR‰5ï\OœyÅëvн‚æš¡ù×Ýyøÿåež…¥1ë~’—ßVKHnbH>ãmð‘4WøHš0‘ÖÐì&€%G&ømžë'ÔôCK2ÝÀÎòZàžú ~âÁKs 1nG ™õ—ê‡æÐt7j#UšËÀ/*„ ô…™ƒâ×»äeš8þÙq0Ôø:Nöt£¤P¥à`çê*$„š#!ìå¯0w`±(¡³˜ f% ¹å‘/θïàSßmÆ(!Ó¼`î “·Ú-çÞƒsÈ0†ÂŸ(Ñ^万§Z.eÐW¿´Åƒƒ<@ˆ‹tq5ÂÌÇ(Å­—ZfËWÝìƒ<$˜²öúDǸ*™»ÌÂ~6ô¨êvk–¯¬­‘’OVÚ§zpHÖðq…œQrF((t4ݾÙÕdBÑfð»·ˆÃ#/ó±GË%>˜VÓ°·ªÀ èwì’ÉHdRGÕ.­°.]Õ> •ÀüVÉ++©nŸùr§;Æ‹Ç[°ÃÁqWø<ŽE§ %¥PÖer¹L£ËåR÷ûÐ..Pª<‘À‚B WÀûÀý<¡õËyh ?9Æ(0yÿ_V[½4h4‹P"¶ëa RÕ/®N®°´5^NT­[‹û~ägF]u›b9îMtûàêf>6Î+ ž‹r²ÔÇŠp=t¼ã' ~¹p3[H€ó`=;Ïå{ŠwiEâ«KÎ?¦·îüÐ~Ø;S.xsø¥HP˜(ÐDé¬C† X˜$ÒÓ”kžÕ ŠøSDë’õÞþpò«ØG~•Òà~@Y·¯Èj—UÉ#.zަñ:ofít÷{4d|J‰kàªàâ<68ò9Z¿êã“ÐÇ".ºu _Q'„Æqž}]V¹Jó¹¦ÿ ߨ ‡Ø¶¥TÈ3Á(ü©ŸÂék>U~ÌJ…_Íx#J@äüU¶Êx›ÑU¬2ôž×%»P_x96¤“"Ô$Ü«¡ðQY&«—N =”£h§‚þYEûwMïðÓÙ—ÅÊè‚ØêˆnjdVÂù†þ2±ß¢[,ÜVkéq„¯ô®OÎ/Éô‰þi'öâæjG4> ÚÇz¤/Ët¸»Ý0¶‚ƒãh2†9~-fNñ©û(–È4¾eýT‰OT¾˜Ãþ{¢ò¡€Œnÿ~Qª`U§­Mõ†¶Ëâ’ xèAýZm¯tò5ÖÃÃæòV‹¢Š Fá H…ÝXeØa@H;ÚŸöd•Ab[ÞrÈ0ÁÖ\z© )’Šû´†œšÎÒ8r@ÿ2˜T"K«J¯Ð¤¨ÞF“%ø³> stream xÚ•YIÛʾûWèH#š½pË-ËsâyAð‚$ŽÔ’S¤I­üúÔÖdSñ‘»«÷Z¿*&›Ó&ÙüñCòƒï¯|“Úì”Mb›éN’¸Pz³¿|øøùb6è>ümšÿ»ç?›2.3mž¥Lœdv“Ú"NÍæù°ùgô©>Ýz·Ýc"õ›íÎÚ4ú¥­®LiêÖ Û?ÿùÝKýôÜ«(ã? õª€œ5%nïŽ]ïP T}¾Îe8 e\?p¯âÏà`G9¿jO`à,z〣ð¡´ÑÁo¼Gc8ˆ(Ê0j:V¹çsu»K5ÙÏñàƒÅÙx U†½Û$ãP~¹…¦ü¾ðÜlR$SÚù~Ü©Èy¦l¿=8a´˜i<ƒ Þe“¼7‹üÌc~ûéðì;“Ød èvI—èµråÅk'ý2°ùp뢾„h‘OèA2yò~ñŠg‡¡ÀÇRÿ¹‘fÊ1u3¥1y hð»ÎÂŒüûŠ/çÍ´7Ó©èÖGß·Æ lK‹ò»¶Œ ËO@…ÔÞßÁØ%&H=j°óTQoZrjd48æé–c„4Pf¿†;®A Taã +»tXW¬E'¶\ãºG(à2ª)Grùy”g“… åù<ò‚Þ]ªºõg€cðvN  á,&K«¼ t¡¿ºáîäðh¿±êÇ÷‘þw :z„½ ?YÄgök8´ôkY©¢_:tà&ó޸剬ҸM ´ùu²•8ÔÀ5wž°%N£èŽgø7­h?›Á§ÖMÃ*s죨äkSí7áfï•í‡Q&ðsëɽÌÎpÄž§Gž˜$°9›LbÚ>‰NzïƒL½§iIþ¦/CäZ×¾ã˜âú澊ÕCàÍŠlptÅF­T`Õ¤Æ3VÛ¿5{5å[póË ÒÅbr àŠìÑTc•Ð'`wò Ð |ôB¡$YƒoëC¼l°Ÿ5ûì¨ig-pQ×îuéKÝEÐö¹åp$pÉÝŠ}ˆÁk?Mì^Á^il'‡zé^Ý[Þê,¶ù4§jߤ;’)µA~c zïûúeÎ;ÃtL®4CXq®fºT›OçÚ®¿°4¡Ÿ¶"B8"^›Åeñ€¤~‹—IÈxˆ·ºPˆŸV%Týe€{mO¯`ŽTÎ>€4g@…ìƒvØ`kº".˜Õ{ûŠ£?uªfèxÅdM²«ó‡qÙÛa°|?¡º}«›º¢d¥ôµhZ6{Mx—/Ã’ˆy,@ Ö(rôZ -οtÃØÜe?þ€±Œ¨ì8Œ¾ic5 r N…PõÍõûz2 ©(®!µ»k¾#ÄÙFÂWΆ‡p«}Þ½Ð*áè0Æ¢ýÙ†7Õ¨Ûp„Îã°#ÆbQÀÀÀàáð¤ÊÃÁ\œjîýdTìá`Ñ‹XK#·±ñýLY[Š¢Gu¶¾ò“†z‚=ï^<Žx6ÇŒ4 Sòdée°?>î͈Z˜rPÚoƒð‡õ‘×ðÅðJRÙ‘*yVŠ_î@Å ²w«"›ŒyͼÅSì›ÎÛwïí¾È„QÏYÆÅ9BNÿÒ¸Éíꊠ¨–a웢 KŒìÀŽ¡ëð~c@!NQb+¡>¼Âäû!*PshxX6ö5úKý®â•äòÂÑš^'Kýñkݔ஧Ò"¸ÝdÝ5Å“7Љ*ƒ÷[>y¸½ W‚6eVY¬ôœ…°¯¤ €Ðp%(³($Ø‚fßyz%i(¶ëvß]®Zù±©¯¿-ö_ÑzGÀ cRÇÎË„j¢ÄAD†Iý×õÝ‚—ÓkŸ´µd%*BÉÞy]˜fcß ZVLJ8øìqe«$wêëÃrF¼f<¿y»_o‚dÀ߆2k}–oUD!ÂXÍêl}:nu-+æœ`!ÔMì×Ê.é4‹UV̺´šoe¥ .¸Þ¢(a'³Àr¿ÌxË0?O°ŒÆ?ÙCüfrôûff††,úÉAHÞ1JÅõ}Cÿ+Aí}p—!¤áÄ'nÖ#rú…v]  Lâ’¤ j”¯L-Á¨»µ‡ªG¤§Z îÜòÊJ.`µxŸ«kï£bR–ùTZÇ[ë=Oßy“2R/ׯ]Ba ±Gì†jh±––Zý]ŠM> 訅å‡,›oÁ±Š_/G…Å»7&Û»TYœ&éÿ§’Ú„UM­|ú¢‡3ºB~ÔÊÉ!FÔŽhü»&ñe¡IÔš ða¬†IR#ÑÞ6u²àë–?0(ð¥êü§eQbQe±"jä|)\ƒNË©ò ´ETYã²MãD«ï²õMlžaNà:¹E)w!Š]ø8ÛµÝít–{vL#„ ý@¸Þç :7þ´"¢š@=ÅÕ4©¢ª´Œ“ôÁ|±äáoXfø:y£?Âø÷c ÒüÛ4´]ì-€ÿ9¹ ®a·)4Bx´%Dâeî[=ŒL©Ûi9‡B¶ŽÕp¦›ïò2>™*Š ù§á“–·c!s‹¸ã"µä½æ 1šOAÄèÉw&:°Cœ$Ö'© K–¼8üXæÀ™«¦þAÞè$3ü`tlr~¢2‹9?=øÏ×Z endstream endobj 414 0 obj << /Type /XObject /Subtype /Form /FormType 1 /PTEX.FileName (./figs/snaplines.pdf) /PTEX.PageNumber 1 /PTEX.InfoDict 423 0 R /BBox [246.136 369.636 348.864 472.364] /Resources << /ProcSet [ /PDF /Text ] /Font << /F8 426 0 R /F13 429 0 R >> >> /Length 382 /Filter /FlateDecode >> stream xÚ…RMOÃ0 ½çWøHx±8ÉuCÚ Ñp±ÃNü}œ´éª Ujóâ÷üüQ[ ørG8‚Ç?ŽKÆ §3ª TDö ÌȆÆé¼3¦b–4Çe¡›ÐÄ«gbìYEsÏØÎ;7»M±±’®ë5îÜþÎ=ÙÓË'øp5QJ½ ÙÊ }»ç±Uc-ï+‹&$fQ™ó U^±›OXf—vZ´õK%Öd"¨)Cˆ )•f{©‰MÁIÛ¤Nl=‡+|ñaáÁJ(Ìÿx0Kße°É‹Îc¸–ßc¶ï)¿ä€ùª&6E2—Þƒ¨íË|þæsê}N×=„ú2/iF¥€[‰Œ–X|AÊf l‹ös,¶}«É<ªpSçX‡^óy.Ʊµd>ß8Y"oo!ÁÈ„ƒ&ØæP}¬†;Ýß§‘‚EÝzp«M†‚EYaØ[t ïðrâíÛ°]mH@±$É•RÉ6-Š#ëÕ“Vž{¬¸_Õ’¿4 endstream endobj 415 0 obj << /Type /XObject /Subtype /Form /FormType 1 /PTEX.FileName (./figs/intersection.pdf) /PTEX.PageNumber 1 /PTEX.InfoDict 432 0 R /BBox [212.311 388.314 382.689 453.486] /Resources << /ProcSet [ /PDF /Text ] /Font << /F15 435 0 R >> >> /Length 666 /Filter /FlateDecode >> stream xÚµTËn1 ¼ë+t´ „•(êu ÐÈ­¨oAéÆiØqZ;(ú÷IÞ—´¹ôâ5)5ήÑWÚêGõ]ýSYýM±ó$œ´8KÑ:½SΠ圴K‰¼½U_Ôç3L ˆ±dWH¦ƒ±ÄÉÄ)StçB2ÓLvV—ØâRÐA—Ëëy‹; "¥è&‘ܬÃó€hGÁ=vpdfw´¸S#‹¾¢gÙw˜ÏÑ©ûwt6jŽä—0Jb,£N2Y4ç@9A+Æ((±«Ç-‹ì)L <Ù)~ y¨o°´­¢â1Äì‚@O¡¯èö æ3¼6flJYOhWÆœd²Oš£«{HPQb®ç-ÈUÕ±‚¡ú´Ãó€h¡àœ;™Ù-.ˆžE_ѳì;Ì瘌z-7Úè;5ñý`˜Áƃ¶M©bü"Òõ Z@g% THs&_^/ÎŒy# ~-oσ¾l,ÞÌã,óg)È LNlµz T\"è‹÷žLï¶÷ÅêLbÐÁO¸*e®îg`/ôŒ=¹Òî´ðÌÕ·ÑÅÓº8•Ñ™’k Ž=m†m]†°‘l²§uñdÿлӇf®ÑyÕ®Y­p³ v`H '‹z !d‹q=³/kІ’peŸ£œ¯É¢‘ѶJÏ2 „Ìj7•_„ÅFRjÌ_Ä"?äîvêr¥Þ´^GÜ‚•­îq±­à½^ÝéëÅnÿrX//œ—Å3f±?lŽ›ýÓòfu¥>¬æl2¤N± öf&øÌØ¿2‘pbÒm÷‡õá8ã²yZâqÊT{~]^ø¼x\wÇWYZØÒÚf6ÿémw|¹Ýn5:‡§ÛçCûû°þ±)ý¸âqé endstream endobj 441 0 obj << /Length 1758 /Filter /FlateDecode >> stream xÚÍXKoÛF¾ûW¨7°hî‹ÛÆ­{(PÔ@M´¸’ØH¤Ã¥bûßwfg¸"%Úq€¶ÈIûÎÎãÛof•,6‹dñóE¿?Ü]\ßä‹".R™.îÖ‹L.ÒLÅ"ƒYµø3ê·ör)‹,rMù€£<ÚÕu´XىЭhz)ó虤‡=.>^Ê,ji¡íêMݰ†²©Hõó|ÚÙør©•ŒnûuƒÙÑŽ<*;Þ}(»r·³»á$Ú^µu³ª+{uù×ݯà÷Rˆ¸0ìayèÛ}Ù׫˥R Úve‡í{¸QÝlh¡v$up¶Š½6¡ãBkViHåû­m@.M¢¦Å_1Ò ‹^+©„­=†%‡PÒ¦?¿Xõõg X YtûàåXl[²\¿í¬¥!ZÚÕÞ¾¶âgdÝÔ뽆œ4dK¯PùÖ®03i}ÜZ ¾wl9ç¥!—Ñj×:ëzš|F¶ëíÍ}Üá·nðŒÞv΂7mC«äGË›,éFji?"jÀ¥ö°Ù"@úvM{ý¶<ù°iûak°°t:Y¨¬¾';MUvÏd°³¶Ú`¬$'~+ Îìw¤o’"²”ª†Äȼñ‡=%¹¥ÙÚ#e¸%]\E˜,)ÇéAÀ›£“6]]ÑÚF0û˜¤tî°+ps¬c=lnÎaÞ¶)ïw¶âe”ÿÖö ®‹!4BuðZ"ìi`>€9Ï$´·´>þðè Ê×Þ¼ëYŒ¨I*gØìOÇ„{™1{‰"Îu>ˆ`Ðé;£NÉXjq¦RéX$é vŠ]TßN`ý¸p™4úpO„°f±HÅ”{Þ9Îòª¦ð(øv×Gç×ÇÑr»&¹X Vþ+ëÍ–MÃD°@é$¥K€ß…K€§yLn6 k¶ç>ÐÕKã§Ùø’ÏkzÊ3­cNmhNa€5es°H×ÔîZïîw¨>”¯á÷ÝÝŧ Ãd–q‘ˆ…ÐJ¨c«ýÅõí^/~j/~§‚™%ë$—U¡î˜pšTmÊØåi‰Ûⓤ’i–¤‰S£ø¶‘)p3ÁhñýyVÓ,Ίp×ß##ÃešÃÁ¦LSg7{Œ‘"Ę“’,ÎÓ@J,’-Ò¸ÈTŽ:N3ˆ6Б&qnšŽuZ,F2W3GÁAZ~ÍArö lzÎÒ$…‡íù2S(ÙÎiKU1ìTùàùÂgÃ8ÇrÁ´ +ž½3•‹{¤ã *ÝÖò"\¤rGD‹e"Ñ⤔?õ¶qÌ¡žk:l+f\Ê0âÈ÷g.ÁµWzØŸ ”!•ŸæÂ’'fØßNiË´ˆVLi†(mÒË =65õU[æ B€N’È&N-ÃQ(ŠÎrA”ÙØ; H`v£gÊ°Š³\žÅhªctÔb^Т8b2È_Û\+lZZàÒÒÎúBÆ2¨ÁGÃ|ß`BBB“4*OÙ0è,FÄŸ[> O÷ìz»qÔŒ¯:ýáü±­×ýòfîò‰ñ ¾:ÉÓ$·K•ð+âük²;„®±e7b¸FÚ¼rà– 5ºÚ¨ê"äf D,T¾_Jö› “ x=;’F/Ï“¤’ÐËŸO K6/”šøÕœ DdÎÿ3'„#ÃSR°2žœIB‘3€Ÿ£goµ«é5HÓ]÷§7ÀóhÅc¨}Çfƒ"9Ã…ð„€‡ü›ª’y­*qù3s¤yš‰@(ä´Ùþ¯òð%~ÿwîÆªGdD¸>ÍUÕñó’³µj'YtõòšApWÝ•åð6k² ÆIœÀÃŒz-yÒkákHÎ÷ZÒ¨³^ ŸÂ¾×’)õZõZ’0(À¯‰Ýó†^§ˆž&´q?žŸ }’S—6 w% Ý»lGã’8lDK;Çàâ,˜vM=®Ó3 Ÿ³.Ð@¦»Ÿ¾Z¦ÖÕMNOd8§¦Vn±u1eœISÄ]8güMÍäº6x@ŽŠœ»ôÝFªà®ÊoºÙ(¾áfã•ãꤜÑ_¡\¦vvZΊd¦<ˆ" éˆû!EéM>)SÜFÀÑ¢°Hð&ÏùÝ¢'R€ªû‹÷ endstream endobj 437 0 obj << /Type /XObject /Subtype /Form /FormType 1 /PTEX.FileName (./figs/example1.pdf) /PTEX.PageNumber 1 /PTEX.InfoDict 445 0 R /BBox [235.112 371.02 359.888 466.764] /Resources << /ProcSet [ /PDF /Text ] /Font << /F7 448 0 R /F11 451 0 R /F13 453 0 R >> >> /Length 348 /Filter /FlateDecode >> stream xÚÅSÁJA ½ÏW䨇¦“I2É\+ô&î­ôdµ ,ü}³U·‹-e‚, ì$oòò^’a /igŽ xAs©›Ããnˆôgüfئ w)ïgæ Õ§›.ÍDаÕR¡{ޏ¹¡tX]½_¯»å|aP±{Ÿ X f„Òä+‡úœtÛ¥û1ÎŽU °+æ"VÎ+.¨d ¥"¹MfÖ—¦Ë̾©=Ëføˆ—¶©TÅ’KVÔʰKœæxBÈ£ ƒ×ôðÊL ,óÃŽB bX3ƒ‡a€†ІÕ$Ñv„ ‚¨  ^‚ÚdAÍxŠUogçƒcpI‘Tÿ¾ê~\u%ëoÒ©ì!WñÐið'V‰Zt:ÅþøÆ­GÔ±“ZbêõTãxS•ÃмÉÍÔKÍöƒ<’82x´±w19Ñ],Ô!)ùy$Ýv endstream endobj 438 0 obj << /Type /XObject /Subtype /Form /FormType 1 /PTEX.FileName (./figs/example2.pdf) /PTEX.PageNumber 1 /PTEX.InfoDict 456 0 R /BBox [219.389 361.264 369.887 476.963] /Resources << /ProcSet [ /PDF /Text ] /Font << /F11 458 0 R /F18 461 0 R >> >> /Length 363 /Filter /FlateDecode >> stream xÚµ“KKCA …÷ó+²TÁ8™d’™­¢Bwâ݉•*Ò‚Áǯ7sû†kiA¹P¸çtæË9i#Œ€à5Ì ¢ÀGˆhð’’(ˆ VË0 ‰fsE2šV˜¸"É•((fMÉŠ¹0°ÌÒ§f÷2°V”¤®pTŒ\€kEª¹)ÉPE@(brÇòó)9ËÒîyñI¸ñ! ¢?)W¬íùÀ¬ð8]YíÓ_£ÇˆpÂZ?µâûλpvE~ú`ÝØ}+†FÐ=ÁÝÑÛñ}7 —Ý6µ* ·8„Iå侀-*&_ùÌ^––u°zn“•2Y)U/N­•Û­4ì+•~Ɇ%ïßa—v§YÄù*‘5¡úæ–}ô?/ñk˜º¬‡ÐDþ!ì÷ vÑñ¡ØŒÅÒïØ¹ÝcߨT‘ýŸ#± Ä´7–±ðFÚDXsNKîÜï¹Ã-gTŸVH%7Ú·Ù=öaý^×ò endstream endobj 468 0 obj << /Length 1628 /Filter /FlateDecode >> stream xÚµXMoã6½çW=Ù@Íå§Hî±ÛMÑ  ÐC·%VlaeÉ+É»I}‡Ÿ’lZNÒö$ŠQÙ7o…Û^ütƒO®?Üݼ»%|¡‘Îh¶¸{\¨ iΙdˆH˜Ù,þ\~ÂD®þºû%¾öîV^1#óÖvÛ¬ÖŒ±e]ä­y–'#[&Áöà Æk „I\ë{·Ô¡-ºÎ™R9^‹ ¢ñ-9_0$ y½I¬B4b’ÆUÔ…U¢Eï7ؽðeÓ–Û²v“æ~°=VgZç‡CYoOb8‰ûšP…¸æ0 H‹ypð<îâž˧TÜ3øö4îUù°¢rùÙÝVÅcïŸO}vÚ­ÖdYl÷E½¢jÙÏø@E8:ñœr‚rz݉ù0J#Ñ>Œâõa¬³oð9-àãb4Îã.aÆB®»ÜL~u¶çûÖé?Ÿï[#Œcð›Ú-šûµWÄ ìo˜†(ôye¦ù²*kïV¿k›ãv—Š·A”Ôaá/çæHáXïWk‘I#X÷Bs¨Ð)×Ö„$r‚}YÀ¢—JYP‹ý¹Ræˆ KY+>[Êf6*e°X€gqƧ˜Om…c5T8V~+Ø`ã‡ÇÖ?m¢U(¸ å ,[þÏîWkHkÓïfÞsw{ø¼·):s/—y[„ošR!Pt;‹>ØÝd#f_<šÎ‘Vép\´]ñàk¦’ØUŠÍ`à #âùÒ$i"ß^šŽ ”ãî¸À±mŸp0ņ²ºæº§›m“¦O…(@í2B 1Fçlçâ8JÎÂ_¿É¹þ|1héDŸ9‘çuÙíÜÝ}›{ž5,Ö#· ÃãR¬‘à )í[Ôǧ|¨ 9]²÷‰¯ $£w¬3„JµÍ)aE$ižÍò!cS¿Î«’R$'¿.r=…,ÑSöÿü]ù’¤wš½îtÍSD“ f RúÃ$£›È-få–{¸)­Th|ë}l›}*E"Cƒô½–¡ôïŠÈ ü_WgéS€JÞž¾.hÄ‘žŒÒ àºu FH†Ø ®ÿ$Œ9ž’ža»4 ƒÃâÒÉŠƒ´i–à 6²°â†…刅•ÿWO¬CÒ:¤‚|„Ç'G+3eŽVp·Ù—UeÎVBkßü••啵yô_k™Öß´Ánã&]k‚,Øh˜aQ»¾ìw1mËv‰nô‡Ñþ;Vz°­Ñ#š¥Ô# ¦V<Š9ñü¯¼x) Bꃡךâ}fˆ˜{ÿ£ÿ endstream endobj 463 0 obj << /Type /XObject /Subtype /Form /FormType 1 /PTEX.FileName (./figs/example3.pdf) /PTEX.PageNumber 1 /PTEX.InfoDict 473 0 R /BBox [182.546 380.029 412.454 456.06] /Resources << /ProcSet [ /PDF /Text ] /Font << /F11 475 0 R >> >> /Length 209 /Filter /FlateDecode >> stream xÚµŽ1KD1„ûýSjẻo“Ý´‚ ׉éÄJQ;ðlüûæ¾óð!6d&3ß6P¼ÐÂŽwR<“iጊ)…Ív‹âj<µ†-™;›øšâ³ÌB­+Â’™jcq[Q¾Ø[º¥›£ušÆáß×Íi+þ#£qæ•«¸$K$v‹5ßã)£WpMtÐÏb¬˜†MίTѸU«èOà EÄÝÉëé}ßÐe?¦FŽü?R÷«ÔñÁ5àEGþ™:×êïÔOìÛû¤0r endstream endobj 464 0 obj << /Type /XObject /Subtype /Form /FormType 1 /PTEX.FileName (./figs/example4.pdf) /PTEX.PageNumber 1 /PTEX.InfoDict 476 0 R /BBox [219.098 334.756 375.903 507.244] /Resources << /ProcSet [ /PDF /Text ] /Font << /F11 478 0 R >> >> /Length 381 /Filter /FlateDecode >> stream xÚ­SÁjA ½ÏW蘢ÎHiæšÐr+Ù[ÈiCZJ ñ)¿Ÿ7»öÚ†æP( =é½'iäL÷TèOÚÓž2½'Ñε iíÜÂhwB^ÇYÿÁsÝË'žkz1½;7}´'äŸÓzSÒRp€½Ñ¸š^}\TÅßìšc9Ù×ô° endstream endobj 482 0 obj << /Length 1910 /Filter /FlateDecode >> stream xÚ¥XKsÜ6¾ëW°öâTY0@€ ˜ËVm{w[y¨*;zša…CNHŽmí¯O7 A‰ÉÒ @ãÕèÇ×ÝàÉ>áÉû+þHûו€–'"¹œ3žëD†ÉB%ÛãÕÛÿËäÇîê—h]¡X™ËõUáÔÝ\½}'TR²Rg:¹¹MŒf¥R‰*%Ó¥Hnvɇô#Åæ›ÿNÛÞ¾3ÑìI »µƒ7×RÊôó&+RÛö+‡¶:êvÿfR¯j÷Å®JÇŽH’ãuÀ™L€B¼FèŒqS$À˜È'Æ4­ŒùQ,7Éu´Ì_Ù[ÏœJ«¯õàù¸F{$ê—z<ÐqY'x}^øÛ¡¾¯ß‰•‹3* ëÞÜÙBÌ×2SLI Ú ¦üÛí˜%žÇîXõÖ¿­ÝŸ›ª_•ú®¯6™I¿ø•D»?ÚU8zUˆˆ‘LVrX9ýõP%3bZÀ.Š"3†iS¾\{o6`>+¼æLé‰Ó‡ŒæŒ‹Hgî SSm½I‚löu,uç/:÷žÔµ„N£G¬*`UåÄÙš= É 3ñ†·¯g Þ=­ygVNᑞ0JD•{Mèo×Äî|jêm5‚ð2ÃÉŠ6×"%ã"â£^–1Ã'FwkšÊd¤¨¬Nó™ëš—ð˜brÛ-X^–±x'p$°û?it>­œœK–‰Ë'O¹íz:©ïFpR4äø#ÏyÄv¿÷Èýëû«äƒÛóÃØ7 Ù;º˜™^ÔÇz·k,}ì΃Åmà[\³Ķð­OçqìZà@°ÍµR*ýYó&]Õ÷€À©ço«¦bã—ÄεöëxÞ›ºµ—ýŸ,èÅÞ9#l“³?nDê]R=Ï%…,/‹'I̸æÄ÷ÃÁ™aÚ ^U¿¥‹Ž4±³oBPÌs˜ÎêÊ£«£Rm½˜­gù;/\l<žè WØØÕ´øÇeኬ<¯W…|­‚kÁ$àÅóÑUåYºmÐà zì;³@®ôÞ_ºZŠð;¡<ÉŸy7HDõÃHÛî"!;ËGrwK-hןæÜБ֢¤(@:ýZŒäóüÄŠó&ì vÛæ2ƒiB´T£çÓL|z{üÍ6v2¦ys/zíûî|z¾Kê—ºdVò9.â`vBuaɾª[ä\òôÇ(~àxF×;¬/=æÝÇÆ€Oøô;šÒk‰#L@T“.qÔ—Ç‚©‚G¿ì„=MñÀW¤xQ4](°àú¶;÷kz¿p¬vÀ°Ëè’/Ò-¨ 8¼#Sú‡þôµ:ž\øÐ"Õß?ÆbbŠ•¿oŒLqu¦ š&0C fñ çd©ÕЇÁd6e‰Û5–bBÛkÈÅDìè oþÍݬI¸¬@ÁÛ[Z@ñ:λBC¤qôÉm¶3ÀZÛÒâá¼ÝÚa¨?;ª§Íp Ÿ9‡Â,õ[9%d„qé¹kë@$lWËÃ] ~ÒH±º +u^ÏÓ›ƒ¿9®p8¥¦0ˆâ ò“Vº{vÇCí{§ÞŽ#jøŽÆ¶î6F¹t9S˜O„6’gp“’ò|ÊRÝ 4;ª‘èuhjÝ 8\ÃMuèúŽlÏöÍß×ÔûÖ^óåKC];%J^¨ÀЏ^Ô>ÜC¦"R¿Í?éÎ' !fESðÚ.à%´?Ý,¾$ã[uZVúÏÁŸù; î‹R½âw ä‡j.ÿååòß@nÆ_Qý{Á* N¬H¨¼kWjh—sê™h/¸`yþr°2¼Ô)wã°J¤ó—J°è‡XZH¦Tq!3 ÎXT;¼Ê%°:Êùtß.K —¶}­¤Ž™aÜ”ÏÍߨ“¿)Z/—¾2K{{„ld {*´„5+á ¼`®Xû5‘ëb oþàÙ„?Ð W;ü)eê~`\QÓØ½û”A>()u&QƒmP5‰{>ÑÌè÷Cî=ƒ×Ïvœµ¢ ¥X!ôe˜¾"–ù.tóâ‰b@Fµ“†ø€Q‹2ÜB1aÄ2éŒÜ2Ó&JÂtg“0…2œ´ípî1á%Ð ¬}$ö¼¨\„)Š zägA¹ÈÿlÛ…|>›³&wmÓPïœÜsÞHBá%Sü^qÅpXÛwǵw×á@ëIYÎÒá°½Ãg탢Öi_ï.縜‹Ì•dHomÕ¯™Ç‚ð‰[õ„PÈTÂùΠ²Þ‘²A”¹ÊÓŸAYÃZ¯!‹ÅÅO50³¹l Ÿ\d®s¦Õ½ŠyB»ù?P­W}Xoϰö«Wêá× X¼"ú—ŒâÚÚ¿¤/ÿ×!>¡¹ÚÇúxïëÏuø ç?„™âL̉|¿æE!Ö±­ËtŽU.3ʧÛãüåoÕ'í endstream endobj 465 0 obj << /Type /XObject /Subtype /Form /FormType 1 /PTEX.FileName (./figs/example5.pdf) /PTEX.PageNumber 1 /PTEX.InfoDict 485 0 R /BBox [211.306 337.235 382.994 504.765] /Resources << /ProcSet [ /PDF /Text ] /Font << /F11 487 0 R >> >> /Length 613 /Filter /FlateDecode >> stream xÚ­UMo1 ½çWøHÇÎçµ õV±7ÄiQAˆJôÄßç%»ÉÌew¨R['öóËóÇÝ“§ývž¾9­‘%{ êéÉY.ì-vë§ûä®ù¦Ì"™BRަ/ø¯ÑVØ9O–kE|¨\%Òïx+¿%Nbªrµt“ï°¢–_â»AD5®9!FX5“Iåubl1oqÖhx[ÙÏù½…+o„«B‰œB"5x+tÏ‘=Ì ä^™ e’v·…åÊ!•+2DÄà?ÅALl1àoå ª–—@[Ä›"{…ÚÕÄC³]£­°%qð•ÔGPD<ä—i‹··!öª;,³ŒrÇ+ ±¨«Ñ'È<çl¤ÞuBl!eO‚œKæÔÂ3ªct|š7í7LAV¡Î-ço3š¯å:>¹»ƒ{÷ýˆ)Ošèðˆû\2*L‡¯ôùÕ¯×_÷îýá2i[¥Rð¯øïYŸ×Y‡~­j¶ZXÓ‚Ö9åŠQSe¥e¹5ëï̹Çmêb.±Óî¾Ãdh}Žõ•˂ܭ£›yÏ·ƒÕˆ]8ÝãÓê´Zí³ ÒK«ž¤5p2oËEì´»ï°N´fl'=‘ÏOšyÏ·ƒÕˆ]8¯ž´Ú ‚OˆbÊ z½¶R]üepk&²ÖÖáíDÛÆ)T°9Uû‡Öîžû@£ëKî\ÑC/i~hE­ß-Žo—ÆÅÃyÀjðå¤\]dŒ#ݲÛÄõŠõq¿¼;ÕÌÌ÷|µ¶o@c±ÙÛp”Ô–Üwº;©ôàþ!‹„ endstream endobj 479 0 obj << /Type /XObject /Subtype /Form /FormType 1 /PTEX.FileName (./figs/example6.pdf) /PTEX.PageNumber 1 /PTEX.InfoDict 488 0 R /BBox [212.272 338.941 382.928 503.259] /Resources << /ProcSet [ /PDF /Text ] /Font << /F11 490 0 R >> >> /Length 231 /Filter /FlateDecode >> stream xÚ­ÍJD1 …÷yŠ,U0æ§IÓí€ ³îN\¨ˆffãë›;ˆã€ˆ )zrz¾Ó2®QðvÈÔð˜ŸAÕ(3ÑF§lgÐl†ÎFìßÀ¼¬'B*uMl­îÈ"h#³À–B®º(ìkeäqð„Rd ¹t?xuû&¼àê ×TQÒ®U.Hnæ¯É²×‘댷Gý²§S¯ÜÍ « ®nDpÐ œžjÞ³Sœñþl{þ0­áz:ZùhÕËÉÍÿŸºû‘ÊB\ÿo–4šü™ºÄÊïÔOìþˆý—h* endstream endobj 493 0 obj << /Length 3291 /Filter /FlateDecode >> stream xÚZYoäÆ~÷¯Pô²Àâ’l’MÞvá#I`)H‚lzÈ #9á±² ÿøÔÕ ´®ÙmËkÐT6d¶&ÁhÅT<{– uí`Â(÷ÃhŠP{t-¦ ¿ò.Qìë4¼eèòÚ“•cŸ«áÈDÇKñ¡Ê®íJEJ—ÔKG ´²2uûÈm´:Æ l1¯P“›üTz㑟ϑ[X7ò¶c`+Úƒ§K&—z¿Šö˜)NሉGh{¼=x¬O{&D¢.ŸÔò/›p­xp3dh¤½B¢ {`øYn©l-sÔ0ÖŠ äÚ‹âT¡€èd–¹KuÜÛôÆq 1!C¿!F=µ+Äqy‚ ¸Ç´ÄmÆÑÈ4´,G)WÝf î@Nh=qìýs—)f¢r¨tÐÔ}+ºOÁöËŽÝGµ²úR•#„Ú ëèYY·B«j_;'$ãáwÁ@è51…0já‘Ôr¯´ƒíNä_pÝ0µ´Ì¼j«Âö«c¹stЗ3â^î;»xì=+þEì*8ÀvS°×?‰>;Wx®¦s±s°¶æ{lÍØ{‹@‰Ý¦•Y-Äwp{f²g<©?¶»êñ89Sµ`‚lràiE[·©YzòΆ‡ž«r8º!;¾4G*›j ¦$?­XÂïÉ<íÜãôBôØc[o¸³ÀaÔEÅùrRM’xÓoù´ üdm«Lcëi?Ì'¯VVx¶“Ë-ËÏ€oaŠáŸb0lØŸÌé\Û~ý¸šuÐ6/âœC‘\ßòDp¿:Yó¬@/Iâð«þe35Jòä ­ºª +õÜ'Ê Öä4b´ÝÖ %p ‘-Îs”÷0䩯+Í`ö¦—wü3›Më’›³ éüÓ„(°éÈ[6s6蛾)µrµÊ#¯ùÜpìñu?$ ;f¼§×lƒ!‚ó0†˜¼´-o™NÎèF¶X¤Þñ+è;΄‘°ÌéÒ"ÛŒpƉ›–\s ¡k»¾ õJpÛ&êž38yûBÇ|i$;‹z0:ð<§É:M½ûqßÛÿŽPÂe'~+¦¹Þ­0$JíN¼§LwÂÉGÓ3±‘ûZrj…œÇ{nÏEÕc«±•ïÃbŽAQ¸t…* ¼E^É’s4¿²:ìB —н+íÕ$ŸHJ+Ч'cú——e¢X·²``ªy/ƒJ) ð½¸YïW"øÞt²¯@;ðoÉ©Úz#ï…)ž@Ú"sâÒÀ¥ÍE×jª¢Ëä="à9Aé¶‘Æaì„0¥œ|½¤ÍËÌ>¢La $ÞÎþ‡v2vž·ýv•€''pþ·3%þF؉^â‡*º,ÎüFÍ|OÜ:Œ û1pôÝ·¯“¦¾N’ßÙ¡ /Aö>ªžXkõãÉöî|Æâ~°Ñ³é­ôéÎ éú=gOËgðbsr ¾Ò~tQºXM¥ÝFéH„¨ÕvUÒ)9M4Bš–ð­<–¦mÕUÉIå@÷¼"òÜ\ aË¡ëüˆUó\ýk†DêeoÝK”ºfèGá$ÌíBö3gU\J .¦ e}$ø©/%Ô:'m4&çÚÙ0õÒùà§ù0X2 ¤õíÉ2‘@žÎ]Õ.c„¬ !kAÈt€+~ô<ÔA/ñ9R¯¥új,¢(”¹ƒ,üUœqê(åPóWqpB_Q(;ƒßÅZC°ÑËÑÚÕ xÉ—]’PÕ›»„5èH©Yn(ÊâêcôVÊ䉡SandŒR[¸;w'…Aæ@2ÿØ´tÿX»(¨½s×îk{ßCú;§%qœ9VàŽìbå8þyF’éTª‡¡Û劾r¸àר;/¦²èF’¥ÔB…~#)ŒtºBøØuúÌ`'¢üŸ2ohuV’ü s_Û©LÎÃ.c™*Ô©w6¢*Tƹp‚îÌÉ\ýl¥Ê½*fÑÆ¨*»+ß«í^/|ÂvË*ö¢®ôéþ/.…žª©0þ!–ÜüÓa ºzÊÑŸ«þ¸Œ±‹ÊL0X ŽîØX.©=¡r䙨×.ØõèêìÃÑÝqU÷V,ßã#§¯dî<¢^{»4ÇšJæg™|õú¦:[Ѝ»»¸ŠNúÝ-_.g»Û÷¬§å˜ojóÒŽ/¤ÉïnÓ0â¾Î£[nµçªæÝmÀÝ@È$Õ‹oß‹¬¶N{ënúžý¸ –š{[¿ZÞvªÐc¸ ¿¸ø× ‰ýlN.ï—zÌßyR縡á4=Xæž›uGH™’lJÿ^N{Î7‹Šü,žÂ}8‚ 8ºOx˜‘{œL÷Ô ‰ ¯ÔuR|“¥{ùõص#[QB™bY— laä«u|cÅÜø±íÅʤl dùR¥IGJn. `r-p:I½ÿÖèy\`U÷ž4×·ÚÙƒílS¸ýÜ·I^+“u¦­mpàÀã˨§¯£Þ›Mq]„O—ß.°gøçÂ2‘y°!õ8ð9Ú¦!ÜQ×ꀶê¥à!Šc¾gp„ÀÖ̳”B+  f”ûT˜^}îÕ>2Fr‹O„º#ï¶“»8ô-E Ä=pñ… Õ‹rOã¢ÚT3Z²²)Ìå¢Ç©Ðòì_/ê8è‘ÇéÛ•â‚ ~{\Ùäÿå¯ñ@AÂèW\õž4 ·O}¡çß ãA­—|œ—0ù'üˆýîöÅö¯ì1Î7ßöïnCqå¡óåýеOx@ÁOŽAîÝíŸ>üøÃw»¦KÛ`… è­ÓßâÈöÅÞòë^¼+à/h`Éß?·¨äqNuYl3* ¤n u^Ê*|P§£ÄÑ =ü0ŽÜ¤ ‚ý‚[C.3v¨E| 3Ì'éÒ¯ã`%Óí -Åx¸m^ãýÁͺ1ñU¦^+G©(öþúí÷ÜØ.ÖD’à þ0E1¢©øsDK…XV\ G—Ï”êÀ¿ËºMÌÕüP[Ï}䎷}Ñ‚5ƒÏã¯=@ ”` ¢tÚ_ÙÙMh·¹ç2~y¨W“¾{øêJj‹‘ endstream endobj 498 0 obj << /Length 2945 /Filter /FlateDecode >> stream xÚµ]ã¶ñ=¿ÂX ¨ œu¢HITp pA>pÁ¡=$ ´EÓ­M¯ÕÈ–!É·çþúÎeÊÒéC_,r8r¾gèdõ¼JV?}•È÷»Ç¯ÞþhWe\æi¾zܯl—ƬòBǪÈnõÏè×ëqÚèi½ß¶é×mU´­N8Hîz®ºêè×Õÿq;^©‡/Vü*ºµŠÚß×iá·nÛ¦íÞÀ¸4Ño‰2Ms×љϒ“{8Dª“œÖO/+'b¼Þd¶Œu¿þ×ãÏ«2ÄêF©¸Ì„Õ£«Np½´H¢áP 0ÊK9UÛáR5<þ¼Îò¨j.²ÔîGÜÞcCW?]'ëžQÚSseHï¼¥ÉY3>Fð½¬EŠ(cÜVŸü¥v-mÜ^Ž@ñœ·sû[’%§î`LF$ðK$ŒÉç7ÀÕCÕœê¡nO°]T ›€T¯Ÿ@û¼%‚Š?w†ñêºô£¸ÓŽÁlDzu7´Àœ'œ£FÐfM ¦Ä ª>Õ§g†õ-ÞXE7FIà²÷7¥Mÿ c\?th¾`(4C£ i"‰L6æ;¬s€à­úåKxÚ̬ ›õ¸Ç 1ÈjlµÝÎu 0“‚ õÀŒÐ^¬]07Ø*›ÑÈéqi`‹…Ñ¥l{é…ŸmMÎKÞnçîCÎøöÇ´‚NÓ8ËpBÀÝ6$mǸa¼ÊÒX'Úc¾Y –ÅEªCRû"ËŒQ±5é„Ð $•Æ ­©@1ÔÌQe¬aœsv§ù1:s5^•Ê~útZ=5ާs•Ãu‰‹ÕehÕPo«£ ‚ŽÕó©F…QàÀn¿ò>¶iOµ ª…P-Éd„! ð;ˆ‘,í%eY\ê;unïÀý¶tg)ÒþcmuÔ^¹Ä›Ä̦§À¥¼Y%èïøˆ‡^×…M€ -ÅNï¬v;²X6¾äÒý.4•˜f.“–€Ûu-Jé…· BqCh;^ê$¢¢gžž+Œ §>f ë$Pñ˜XÒ,¶¥°û±ÜÈ@Y;W×gãâ¹…”i\”£íÿ:…mP¾ñ©×Œâ2–~ÎµÛ „¢1|?òÅ ò|¡-Yn‘ŦLWiœͧ¾_ðXÛxº!=’n³8ÓÈk¬€e‚ÿ0³Uþû†G“näV{/rtEp{é„™ûäÅf0÷¶ö7ŠDº°œ¼µO(øèßn‹Däœ;9Êõ=¹Maonã%qÙX+þïâ n¥ ૆ÒCÈe¼2äµ¾î=w”Ç l­Ù‡ò)8$3Šã"Û$ËROeÛ{ëdm"q=­5˜`¿­vT}ÁlßµGF‘h5 Ðä£ü={ä¶iZtæÊž;†ŽR"|qÞñŒWð Ó!ÂY"«)¼Õk¼^½köKŽšL]ôq]æQõ•Û+Nü³(ãÂfÞ?? ¬-Ù^Aá '/uàqZ¤hF€ð‚P ”Àz:sžIRÅ[NŽklŽ Â®·çj[³ YÉr÷‰ŽƒL¼ÑIÎ÷Áï €~‚0eéŒ >\ݹ}uiPÖI&•}ˆ.™² ˆ–©Sø´Î ÷õ6®ûëB¾,c{K«"Uª]ñÜ€mW'oK0 e@€‘_4G¥|û²­PGì ܬb"¦™B¨OA³TIâ0Эcjº#Ž9kÊB_¡½|ö€ .áÓèiœyÛÕgÙ ÆÉžJ7ƒÕÂŽPùIïtÄ0_½ÁõÊBêÞÀ=¦ò7 œ¾°Á5£›’´¾F’cé¿÷%QçÉ6P•©8Ù»úìú"J–r»ðÍCèß.Ýö_óîÊ’?=ðü3^÷›‡$ÎÞ.oëývnb›$.L!×” …¨‚É(U3Ñ"lçã)I&Tpô¼È#Ž(͘4¡¶RBN9í§ïdº^ìª H 8°î·NQˆN½%œè6_ÖJ½isë£9$@ -1 ˜$mòTb¡†`DMS ÙO|/­Æ{ÍćQjçTI.¤JNGÎþY µúvutÇ ›ŒÊý‰‰ª…­še„ƒyKK»¤Oéh&žÅhä`&O¥²N²î®OýP¿ üý¶kŸ<½_ˆH5*»[ö#ò_zÜ@¯û\ï\Ë*.À™°ðh;ñÞç0* #o¡_‚º­×é}ö®.“]Â;À÷¢Kê*ŠÈ5SQ\0cì°A%—-çÁßúÎ{!¾½½¤Elm)ö«W,ËŒ  ·2vÉŠ”…š©ôÕF—vv—…l’[Èàc:>âËÁŒ8dùÂŽI„s1P¯ø³s;h£ÈLp:Kw¹.=W¡"îí±g#aoñ÷À¦êžQ 8Þ·cÁ)èûöMiâܪ©y½†µJ¹óƒï sAÃc.‚™~0a“ByÚFß·§? ¡»rÆ£bA‰ðó›JåöŠMðÒA`øññý/ˆþÓr&=¹=\<àÒåÙÉߨTö”dó{ÿñ”%/âìrßäq}W ¾l%2tÔóÈ'þž“Þ„åó0­>oo”0©™t"hrÝ×ÛÕ[LÒ˜×Û#Òãë&»°S±L_©‚Tjã¼û¼s‡uØr5T¤QÇב ×±Ôëê,Nìè´˜Ÿ€At6drî·ØŠd·Gh ]Jð¦c¹VEH?^ˆy“ÆQác?ÂÚnÉý Öþ·TòÒ.ÄJÁRÙÔ[ë-sû· ¯%¤ÎæºôRåÈe> stream xÚíZKs7¾óWàh_ðl-Wªli¸*©MÙ®Ú$*ôÅÌÚ¤—¢6öþúý$­©áC‰s؃Fx40@÷‡¯»1 )*«B ʹˆÿYùèUÈVyfÔI…àPO*ZùTòhˤ2Ƅ̪ ÃJÈ££*9«ÀÓyÈsTøŸP`å‚G¡8åH¦-V9˜ƒ3 ¥ %)W£ +o£Sd± ôº}ŒXPÁë ˜PHIe§|¶X2K<E¬‹# Ù‚AX•/+Æ;l Åx©Í4"‹yœ#H¢ÇCœ,º‚Ç$Ë X¨`[¨Ç€ÿPRÄ„äðÊ•‘5EŒuuãyD“™ûÅŒ…"ÝR`E#ÈcdÀü 'ïGMQÄ„cçäÐÊX7yTJ°˜:)¢äsH«»$+S¨Xw@QÅ`eRV‘œ•IUŒÓÄ bÎRð*l€"FAC#¢¬’•ÝÄ„‚(zKÊ¥óŠ á5)ÂŽ„ͦ$Û‚¶S«Am)×H!KTbçG bK`$Û„.`(;Q6’=ðG‚&QfYÀAY¬&óM¹Àp”` +z„Ù¦8",Ž•áì›v,êCW )DŲ‚9b—ÄIÄN8l@d¦$ºVÀ!´€+b®b1ìTí{U<àM° èBé-&”ˆŽ X)$¯XK„­%={62o?l”ùñâ×fdN¦“y3™ßA Çðõȼnn§w³«æ¶ž½ÚôCs=¾x1ý¤Î,ì–‹?aŠÆBÎ/äžO&SLuVO3ZÔùè›oZ¯¬ý#óæîr^ëß'ÿ™ÓÙu3«S»sóyeNÎ*ö\s5Wg8:¡Ñ‘f/øw:CùÑ'͉ ÷\={¦Ìe¾¾*sªž|w3ÎñºFû§ «X.ä³UÂy­ÌO?ÿ"‡7C«“»÷ïÏ·ÉpÖ°b¯…;:¢/¡¾úê—,çw1æ%Ž¡÷˲cV÷Ä« XÏÓª‚ €-*^È ­z03`³¬T2XV‚Ф«,Çü8›^½i .Øöô¥2o›Oóu ¬=çžÑs<Ôèy±M¡æG4¾ƒ‘ø‚‹;rÔ Ô; m´ýíÝå-ÆŽ§Í:´ÍÜRÀÀè$êhë1ÓÄ’³Y ¯$®1§a vd„5¡°ö(ì"¯ ¶>;Àƒ{tQèeÌqXãÐû½°¶œþdÖ\̧3õä^“µÕô´®èúîªYk­¢ÐþéżQONÿæ­-@Žwðh¡@à‡éõZ_pž<¹§Ý͈Š[ˆ‘FÅg·ó“w3@bd¾¿hUþ9¾ž¿“cª×á|a¤Óæöj6þ(‹¼äÛ·M5`(Kºýûäjz=žüZ“Ö¾w[Iv­•`§­¥ä˜t§‹TZ5h¸>ð)P]Ë\Û2N~¶JXL,¥(%ÄK‰ú,í1õ™ ð×þ¯ÊÕÇûr°÷õ•œÔ}_kë[c{¬ó:Öè,ÀD‰ed­ËYá×7)¼ô×^l_á«^œÇñÍMD vϲ3ß‚…ȼÓÍ{‰7ÍGѸù|¾Ó )šçç"¨]þK€ºüÔ2¨Ë×µ80öÃN®#ƒ¨F|;âœÜ6%Nê§\þ&~[½ú ¹ãRðÕÉÖì1ÞŒl/\–dîo†ýKÂ8¤£® ÒÚ!y’‹)k‡0oHÎ|%ó6wôÜ1@'V½oÕ«³}½ò©$Ó‰z0MÁñBª=Ë5¸CRÑl5t0†„µèORîa£—®Ñ%B*2$CÁ Ë \pN§2ðÞeúÆ»ïr$Ûˆh‡šÝ³zP"“å…°)"} ûAîÂqXãÖ\Ú kä7G¤³æ Ýͬã»[\w°Þgïå&ªçº“\]yOÑíFßr˜1´üåÒãô} yZó%ìš/‘[£½·£¶ó¦öZ8n #ÈçÞJ\o%¼³Wsd¦›É%°ÛÌwscÑ›`ÂÜŒÿÓœ?¢™½õýmÑl±vO3—¼5.ŠNù"¸I.¨´ï”‘ "jjËøµ[µ'«yÙ°-eÚò rr¥>×·,z3œ-Ëõ¹ÁÖ!ôlÖmhg[—l.Ì¥¹’ Ó,b36¿-âóÁLÌT"`bfnÍÜÜ­E7B.Ss[ÆÁ3¤¼Ø£Üø=( ”$—¤™uNÂâ™å¶+ítñÔ!Õ®gn_´ˆ¸' ­Ò*N"TâQK®Ç±¡|%Žõ)Ò†Ã/è yÏÃG¥Í±¶}öRA$_ŸOëIÅõ$‰è€$ ˆo³k'l”¢®ÌòD8‘Ý€ˆ$ã@Àry>_¸æK,Ù$ˆ+Ø ç›’–»{'í‰7žf*½½­ç#’Ìì½7âÖÖ¤òegÁMúèwæbóq6þÐìæ>–ä#É“ù·˜ÂÜî6Š™N3ÿ}ú¨^§Hî¿ø ü}½w¼Žoã ÖðòMi‰¨øÇ O¾|¡=æš1WÉì¢äþÙIËÂÓáÍîPŒpþRÛKåþŽ;Úı·’Us¿’´û•TÊæd7˜6—-x&3‡­ùd>›ÿv|ÙaOØ‘ÃÁ@% Ë«‹–ó:Èíyt²n‚Ñö…»ðö癎/må$}yï$Q‘¯ªyUâÃqépê§(ék¥( ‹¸Ehߨð븫Nb°~ì<Æy÷ÀqyÌì1‰7¤ø@¸âÓ#ZoSŒdŸåº2°–ËÑaæ*ä¸#òÑÆ(ÔËTÐ’X¨·d+>t² u'4I_ŽUnÚƒhå«z%wh/$-ìYÂ:—ôÖ_[Èulëé,òÎú@Ž-ÄŽ1ét‡"&ïE·+íXÚ!}Hyø»Þ9²¤›A9ó²ßFš¢ÛúÍp§+š>fØ0¬ââW3 û²ýZ ˜·g òÞ ×0lfÀ‘¼ü³÷=*óñFg±Rÿ—#œ…œAvÃç¾##?àðÚ!ýÛû v>ÛwB•önÚþA•ß4}‰[äwZ¹uRKï¿ü逓*z*ߺ2|Y“óÄÚÑ‘Ÿ:¶‘ãÁÊëz%¬¼Ðÿ=ò9w endstream endobj 505 0 obj << /Length 3867 /Filter /FlateDecode >> stream xÚ…ÙŽã6ò}¾Â˜‡éV$ŠºÁ3ÉL0‹$dzs Ù¶-ÛÚ‘%C”ûòñ[%Ê–g_l©H‹uWQÑj·ŠVß½Šäÿíý«¯Þ«2,3•­î·«\­²< ãÞ6«?ÓWææ.ÑI0ìÍÀOvßš ??ÜÜ©"¨øåd+o»Þ­’±u×ÞÀÌ¡â?ÞÜé\÷0þŸû~õ^•**BU@"ñ¡µU›g9 x¦§ ¶Nã {æåþ²<Œµv‹·§v=Ô]{‹t¤eukÓ®+‚gÁ:TV¨ÆMïêNåi¨µº‹ã°L…)œ:Í‚ÿÞÄxò8X¸.yOF±n~¦9Ï0ÙðäæÅÍ®øá©Þ {~ì¶ø¯§±moUHÄÄ:,á\LJʤLüËgü ‹4BŒSÓ ¿kòÜ“Žoq\„é(œ¯ Ûâq¤(MvÅ8Š ¯fæQ8í©‚oÙ˜^ÈÙvþ*»7ÇÑm"‘ÝwJaesæ¯vAI”æŽÊ?£4ú¦;OC…šÁl—ú–Mkå©êk0] –Åè”uü`ˆÜžr¤ÅUw$^€N¼ág ˜î,#IâœO G²üZ[“ûëùŽJˀむ”FŒà?\µ¢~r®>Ð|˜ ØšBÜòR21™ %v.FšÚÊ–âcÝw­“¨å¦b™,ª¬ Ù£YƒÝËv·ÞÈ"·ƒD'XoñÔÎG:B:žÕvBÆOv¨·/tÚhcަ7»Þ÷Ö”4ZÖæ\…YœOÎH¸êë!.¤zA-KŸ¸NÖ¡ÎÙŽòÍÐ .yÚ ã–Ýó,ÓµÌñ<“8@cCºR‹û‚RRqì„áNvx³î» £ðò3èIÕ#Çó÷.do¬ qží«çØÉWòábè0¦å$¯}U ßÙÝ_r¾TažŒÞáëj»… Ø®Ó0Î’kl¿e/nȤY.´üx³f’$,uføôXè)Â<Õ n?ÉÀ åSzðK]=-øð’i¾C[¶bf+rk $T*O0³ HñhI*0—X¥´Á‚‡Cã(¤äé¿î+¤¹HƒÅúO`‰‹Œ Œüôí{~ïn…ÝF” O5e\0qÒ7OúV¢kªd2+å¼°¢Û• iêO7âÈa€¬`¾åŒ&—¶ž: €×s:aÈ‹$ÀÔF«à=¥6=§¼~Î 9؆úäÁ+šCo%Iö„76Ó3xÔô'~3<È1©k^vœ,çä×ZwË“k¶(ÀÕצÝã’ëœuxá|d t.R´u×pŽ5¦.ôüH„öC½®l¸¤ì˜Œ$¹¯ŠK±°ôS߃;ÔbXrRkkÎq`ð¿éaµ8Þèqaêžžg’oZ‰ÙSÂ|^ŸH¸9'k! ¡Èò§Î ”J8`pʉ^Yd0(å¤9å¤ãJ<íkÌ®qÚ‡±¹ÉnÐô5¸äþ…‡Ùf9©â#ô×=&áRP% Ê%ذ5HÌcrÇå°Ê[~ò²kAÄ‹wU àJL±åÀŸ­0Õˆ…'KpQ¹éZ¨šâ¼t-©Ln:û'Á<0XÜÞyü>50EÇhv@´Nr9Ù š¤@Fï¡!‡é÷À‘‘ Ä"¡ ÏC……!ÎÚW°{/`œÿDá•x8ËP…ó ³NlHþ’‚—ä,CÑœý¢Ë±P<±~{‹eŽÔ8IàÊ ]d"5—~òp‰è}îcñRŠ%"ƒQ3ƒQãöjf#J4þ ÿÊš“²æeºÞSÿ¢õ‹l@Ô¤}Jò/ÃÀÇÚï‰Gk»¤š`E*bJñIã )<¸SÏfyŒ½yìu§àÅEeì!mH4 Wˆ]ª‰[žj*^ ŸHª£õÆ¡¨©¨×–•€G•ä” |ï[JŒ&\³£_r;³Óü%Q(ͽ@Ê8š¥Tc½ð'wTݸÈÓw'RáttL=¿‰Ë InFµq¸1ÅD$Nƒ÷äÏ]vrËiµ·š£64Ĭ±²aÄKb¦ââ÷Z$[—à+žÆߨ\„a§’³Ç„„-Ïi95×8.¡WB9qXWpFnáLÛM=·®iˆ…OãAÏõÌgÚqÈÜ"‹@;†Ü*-i „ÛñÁO¶2˧x7ÍáØ8ùEÖbM:|ay÷-ùÙªêp„G´‘ ¿"}2{Óví¼v¢+wt]õW5+4ò-W®é6Pm M„ž9ý'Ú4ǽ _ƒNÁì„åÚ1¯µÔÊ *‘±Šú‘L³L`Ÿ޹‘ Z|\¬SJ¨Ãòd¡™›RÑNº$êìBýŸì3‰B•fç•WyÜQ¢ä¬¥Æ†G"¡.±¤æ¨7\Î^hŽÕì˺³™Ìx8€P0„ª;Ê«×ÝÑ„ÍcLàÆê1gUbýú JÏB8‡“xÓØÎy é‹B °™œ”@%:±a¦.þwTÍÁë¨b¯Ï|š;zG->̵™yÍ 3g¨ŸÎm»~Ø/¹n‡}LÊ*r<¥3|˜åRe,c—^Æ^³a¾î'\Vüï#¿31ÞÀ·cÌF4­^$»ËÀð'Çtú=IÃkm%Ø9;õ¢¤µà÷ŸåK2–°Œ2-ÿóZxhªíðw¼ì)oâŒj~@,kœÞOê £saÆCàVÕ@¬ ¥Kc'?²Öta?%#,+Ñš…±õÕl7Óbu;6næ*&=z+Ý‘6Ê ~ÌÞS,6¸çKÀZ˽ç#™d[{m!¾júLW²¦êJk"ZÇr"q_XhÛ/†´_½ÆÂáT;KÈ¡›`2Ée«ñ¸:ËÐ+jrPœ&PŠ€ bC ·êeõ¼{cÒ 'ÄÕÁ.yLs”âÏPõäDæU¤*¬˜†]QŸÓ¹-?Ò™àÕB@ïãÈËønЉ+;¹b! ?Ï´_Éí/ ûU”Ç«ïÌñáçï^­þ õAçöõvøò›¡o¾ü “ùn]¦8²¼V”Ê?)ãÑÄA«ø)pgœ?ã+Ê4šœlËÌN£Å£šÑIr”ÅŽÒ.3Ìëý¤æ2›Óˆ"b.Öjgnýr7ar;„uá”D=†Â…hvðT@úÙàÆ?„OU¾ap\ì«P—c‡ú#‰ãÍ Hµ¾ü[à€ð¨*ø à"i‹£„®Ãh\¼­á?ìG =ˆí lÑ|P9^pŒýPÌ/ؾϾSIFêìféžèÅ.þz‹(Œ½æýR§4ÌÔØß¿¿Éó ¿¡H‰ä-`Ô:ÔjLŒ̼X™.…ðJ>Jæ4»Ì1?)±@dÐXF\ë’3»È5yR,‘ÖU=Õ©N¡aªô§$Jå+çE0x¡ß£›@@’ÀEB Ì÷»A y¬)R`C‚[Àdױ툭FÓÔ¬š“Í;)/ 2D6«¹e çU‘»…ÑŽ»á˜E¼}û/œñÛkæ‹{mëÖùvæûe¹…“$lpÖN´SÇÛÝôf%D¶ZèÄòýzR;/Á]»œ"ØZ]„7ý®ê]¡Î¢.·S¹}@éû—aߤ9­÷q…áOûz]@cÈT›Y“Òû\ÆÝw\Ïxð&S§‰×ŸM•„O×í¦’¨.SÊn´qê™>z Ñ"ör0HÆf7B8ÅI(XcŠŠ‚°©!ŠÐLn5¸g‹nxòyW@¬JW5Õë—ï~U,dí3^ù{ s$)t$W ܯ';­Å¶—×YçÜ% "©s¸0|³l수Ë5ܰá7—DEW.uÏŒŸèñâG{·Ÿµòk£”Ò»û9¿ÌŒä³t·˜‰Üb¾¥‹þ û„yùõëL·PŠ3J\Î&½»õ?9]1ú endstream endobj 512 0 obj << /Length 1383 /Filter /FlateDecode >> stream xÚÅWK“Û6 ¾ï¯Ðø$ÏÔZQow²™i§If{è´S÷Ôô@[´Å®,º"ÿ}ôÚ^oºm=‰x|í4ÚDiôá&åï÷‹›Û÷Y ‘ÌË2‹ë¨Î¢ªÎQWÑ¢~뤘΄ÈÊøÃ([­†i.b7åuï¤sjìôÅ·ï›hžÌ+@”4š‰&Éç„,³- QÅ»©ˆÑ ãÖ€áå²ï ª=â¶Œ!±íd«Hd–ÓYYŪ•³$yÔ®£ÕÊÀuì´¿joö¶?ð :9lô°!È•éÍh“鬚§ñ¢Óì€fP³và°_î­j1B”OEµ6#*äñRzø‡ÍhöCk¿ižÅá”bÈbTªãN«O¨¬ø°Stªû~oµHlÖ$uݨԬÕ[5à¡ìéØî:5*˺#鮽ZE15yü“q* Hw-€<WVû-×óYzdE+Ñ&„-â–Ä€í¿ï~þ•Эt‰wUɼ(Îý]ødgT_b:ØBà ÁR‘†O |>×>:oÌ__°Ê„A•G> ÷¬F%&=Ê•ÓÇ:‚Ì¢+ÀÙ"F>ô– 5¯UØÖ¡æ¡W>ÜÙµxm§”ólÊ¿L¶<–ž E¼Üƒ}¯ï5J;µ¥U¯­cæ|LËÔ*fâ >;fÆíƒ†àÂýVowÔUÚ9äÿc*Š‘.òsJ<ž)›^Z{˜-1õÄÃeÞPr`¦ø¤á¢×ÓÀ«‚xMŒ•Ã3ÞÔ¸ ÙÚtOh~`e󓉕ÕY’à©÷ð7$R^6èÙrZ?úçC®Ì’º¨ƒ‰ÞÑÝ|¢ð,i"Šü ‰³¦ŠïwÁ׬ñCf$y ÷¸–+VåFÅŽÇ­ï242öÜWk$ô¶R{ĵô,cõ5­qâÎð½ªÕAXž÷MB4¾góâš=›!ä±gëËdÁ ô >ó³™D˪Ë3Žv¤¤Ù†f¬ÕË^‘ˆ*ˆd:B78œ:Z<$ í\À¯x²Ü³å85xe§ž[\¯+ªš[=HVY•Ÿ¬oE\(IÓ4«r ÄT^X¸QÒ²÷é¾[‰yö“·”·4)ªóê½±ÎìHˬ×V¹»Iš¤å~0ÝMÃàÏB»}{ WÁæ×Áž0Øìš{·!AoŸÏb2œQæÁ=;<ÅY¹ò×—ë <¸CÝ„Ž[7š¨LÊÑ­á×Ç»àõE1wj¸›ä/W£äÊ…ï– y)ï/äââà%y÷…Dch¯MrhêGÝŸv/¼ãÿ.çï7ÝX¦‘ˆš")çóH4u’ͳhµ½¹½ß ý`n~¡¿-§Ž5•¢ª“¦b¿¾£û0ùa¬`%`Êè³áöt59uÖÕg¢³¶Æ2eU"Jqù¾P§gi¨pXðçùp`¬Lª¹øçž½Þýÿ¡÷/ZÿÜUq‰T½ˆ$^åÑW¶¸ÿZnGYZ'•¨áÇ`‘TšYz¦Äÿb7þv endstream endobj 508 0 obj << /Type /XObject /Subtype /Form /FormType 1 /PTEX.FileName (./figs/lingrad1.pdf) /PTEX.PageNumber 1 /PTEX.InfoDict 514 0 R /BBox [0.5 0.5 399.5 199.5] /Resources << /ProcSet [ /PDF ] /Shading << /Grad16 515 0 R >>/ExtGState << /alpha1000 << /CA 1 /ca 1 >> >>>> /Length 110 /Filter /FlateDecode >> stream xÚM1 €0Ûï™]ìQ|àVœEÁ"UP¿oÚ‚³p¹„ã’tPlrr?b`È}+Š•Pìb›†2!Þ{ âh´4ÆÿÊ€CG! Mê'Æ#sWÜ󎲽¦EkÜîgP,u&C endstream endobj 519 0 obj << /Length 639 /Filter /FlateDecode >> stream xÚÕTÁnÛ0 ½ç+Ÿl`vLIvì¡)°aë° ÈmÛÁĨe–º.?Ê”S;M»^w¢H‘|¤øÄ˜mYÌ>Íâg䯠Œ°LFIž3™‰(9[·³ùç8û fßfïW³ùMÆò(OyÊV–¥Q.%“©Œ8¶*Ùwÿ] !üµj[µ·géß늌jC²+ʺhèrk•jðÌ7š®kMWF‘^V?b{—dÛZÉã³€ß8ÿ¦¾³iœŸÙÕúmðsõåI»ó¾uÊûe! ‰'ÔÅ•+ËaÂ_´ÕÒC´Æ#ƒ9Ð@}8ÓZ©®ÔK/”¤CL’“ˆ'2ïÚÖÆ ŽdŠØåÉ€­:›Últe–^|ÂhT·ôÀ%q›S®øŸy`šç¬¦!Ox©¨ùð"½Ï”î SŠøªŒä8‰Â 'kâñdêtÕåÚYÑü§ÛJºÄ<=8ÏGèò(Ͱû›Òöô¤J@NÃÉï-„ûZ9xC…íĪtçq„Ž\¨´Êù»§[I‘ƒõˆ‡FõëÂÔýO@ÓîêªàÐ7†ã')_GWH“(‹3 ³£9¶…éê?KO\"žÈŸŽ›ºi2LÛ±þY²Bv™Þ—¬Õ ì²å__lÿãj´ŸÀ-(”xyAB& >ð²k±¥c‰ž¸*ŽvŽêž”‡€/PiÊK˧ M£­ !J¨†îܼÕ]½ß:Ëd!¹ØÇý%ìþrÁµÛ•®”ެÚXõØTvWUæ•$‘}ç“yU*m0Ûhšp6ˆÿpïÞ`òÝqøiŽBD¸"ƒÃ$¹õ8´_ endstream endobj 509 0 obj << /Type /XObject /Subtype /Form /FormType 1 /PTEX.FileName (./figs/radgrad1.pdf) /PTEX.PageNumber 1 /PTEX.InfoDict 521 0 R /BBox [0.5 0.5 399.5 199.5] /Resources << /ProcSet [ /PDF ] /Shading << /Grad16 522 0 R >>/ExtGState << /alpha1000 << /CA 1 /ca 1 >> >>>> /Length 110 /Filter /FlateDecode >> stream xÚM1 €0Ûï™]ìQ|àVœEÁ"UP¿oÚ‚³p¹„ã’tPlrr?b`È}+Š•Pìb›†2!Þ{ âh´4ÆÿÊ€CG! Mê'Æ#sWÜ󎲽¦EkÜîgP,u&C endstream endobj 516 0 obj << /Type /XObject /Subtype /Form /FormType 1 /PTEX.FileName (./figs/radgrad2.pdf) /PTEX.PageNumber 1 /PTEX.InfoDict 523 0 R /BBox [0.5 0.5 199.5 199.5] /Resources << /ProcSet [ /PDF ] /Shading << /Grad16 524 0 R >>/ExtGState << /alpha1000 << /CA 1 /ca 1 >> >>>> /Length 149 /Filter /FlateDecode >> stream xÚM±Â0 DwÅÍ ÁnBJ¿ [a`FA¢B-RËÀïc'-tpÞ%¾sdÆ ‚'Mz~ˆÁÊsK‚‡–`$iåP¨5Ø{f ud4š‡a¶”©ªqÇÊÿ¹t‰jvRǘo!þL&Õ“HÅjY¹ô‰¶~°Vò®;¼àa;ùò±5FìÛùv—ˆwNø+²2— endstream endobj 527 0 obj << /Length 2247 /Filter /FlateDecode >> stream xڵɎÛÈõ À¢jwÓ<ˆmxÁL'@ç@Q%‰iŠ%”[Š Ï[ª¸‰í&¹Hµ<¾zûæ.v wñùkþz~÷øÉ‹©H#/Z$š@ÌÅ¿ÕqÏi`ÌšxFd# _Š ÆÊÅIÂð}Ÿ1ú~pO*ÞòËx½­õaô…ïkm̱n Ô¢ÜzœÄ)!“Í[]ó9»!Óüßf¾ì9dõKG ˜¼£P)‚Y Ò`ÂᧇÄwð ¶âŠC UåEc6Í…7;ó^oùßø-­MÜ3Ž'xXUbð(¼Wµ;K¢„ãž©¬™˜oªÝ³o˜0ûd^+ð8Ыl†Ÿ!!ÍïA1°éìöf_ ìáqf”¢xyQ/~ý~ÿ™Õ¦`EÀEs2ÎJ»¬™ Z^$Â$¶öþ¥zir VÙÕ½{.Diá³j3&.×ÄÌ·Ž¶Ò©•–ïXë°œô"ˆŽp‘À¼jLèÿr´‘­†C¯9Fß³‡"ò}Kñ¯ßv­.ÞâÎ…Ÿ¤VlÑ‚uæQÀÅPâzЋ$I4!p+!">Yšsˆ€ÝšÎtÙð©ñXÇCûTg”WË; _Džó/p«f>&D)=þ"ƈ8ÂÏ3l1ýùž?{A+Þ±Ä\¨ €Y¿ËcE«'îe•ŠDF}Ê ½µ®lêlÆ-éüœöÄoSnÆ·‰$V$ìZ0“=Fi‰§n!ðÔ|_F2ÞÒ§AH8v²DŠ8”c›AD yEPvº4ïߌ1=¹¹ˆ\\`ÉÇÑ«Ïwx±>•¯_WaÚÿi²îÞÃb¦«Î LÖ¦î™V†_¥lÔÿÊl­JRÇ·úðËç¸Ëi‰¼k­6·ëxÆTýp»ÍV›£''¥ÀD#ÀFÞªÎ8@"ãä²c4VV§Òd€õÐ[§–%XÙ@¶œ3úÒ$"?ƒQü?åZ©×\Ä®|Uu:7Úo×úL‹_4À\ùæ$ÑÎÈÌ,¯$Ø5“˜ËZü¢Ú:ƒ(@»­¶Y‹w5/ª"7àj¬*L*Ò•²-ª¦Í* nj Zƒz [aꙫ3ç\…³ü%Û©ë±òÚÛŒ¤' v!Ô/ýpèI´%¢âAŽHw䦜aè–‹yZî3„úFeß ˜%FÎ0ÄÈIá´1ǯslÒîøZ+(£®XW–EÓÞ®?˘ž×••ºž‹§¡è‚éqvj5#—±7‡Ý…GâµEÆNp!D±#S»ò\/· B>#'« }jln ĤË‹:/måÆÎ ¶Àú Ÿä|Þ|¿B›ž¶Î (˜0‘Ù¢„²ãÊ”QKP™˜@b˰‘XÚsXâ6j@‘—ïgЉßþ”á aBdÍ;Q× ¼ŸÑm,d:Rî$SôR¯ax»Í9ÒU:NWŸ5µ‹øó}ê°XIþyÑ> stream xÚÅWKo7¾çW ¬šh½ïGQHÚ´p‘C‘È¡éÚ¥$"ûÂ’[0üß;Ã!¥]iå½Ô¼äp8Î|ó ·Ø.¼Åﯼ ßw÷¯n~ ÒEîæI,î7‹4X$ièú)ÌÊÅßÎOÛž•‚7j¹ŠƒØiXÍo¯Ö¬ª®ˆ ö‡YRѶ})o¯VÍ}¾}¼ÉÇÏ®~^þsÿÇÂ÷Ü(ñ+ßwóØ.UÛ_»ÙH®n¯¼Ã!UÛß^ùFŠù\Ý0Ïȉ/Êñ§rN”²rV­¬´k“ ‡íëu[í%»ïùÜE힎©í¨™êÅ#häzÑœÁÎéæ&QUàšjà†`µ4þ>=ÜÏæ3Gå#³œøêïð¢ÙÈ0óFëzÎêuÅ/Ûè³F%ßà§bk^ Åkñ„Óž É×íã“çÆüñYÓv07m­áB^ë5ÑqRå‰óü¤ð÷’ö !j’…¹a”6p0póÈlçûpæÛòë2 Ö¼\®ÂµéD!"ôVDº™®o„üµc½h¶´ÿSü‘†%ÿìùQ#”hI¤0ÂÑ~úN;ôç»À°T 5oG‘.Ù( o27ÌrÒäÓ8WQž;ƒÔzDyæÜA<àA/ "Ûaé;=|G0ÛMHA%`7)õ|yŽP´.Œ„¢ÕË_—AêðFfZC¿"ƒ6¬(¸”4¶\²­9ík7feÇçxjÕ0t6}[ã(‚=pGNã³;¸Ý`Me…â PE’ ã/ 2ú|­È¢ñMœˆpÃ$µµè¡[ƾS‚iW5“Š÷çîL`CjùÕŽ):ªf_´YÍ%ÕN˜gr¿ÌBÇ5Ñ{n†Óh¿×f~0ƒ{i˜e~j=Œ Ú:©S 5ŽÎÎÃÌ‘ ÏßÏÝ1ŽÜØË¬Ît1eŸ].s§±åÔ’ÁÙCß·CÇ–¤ úZÐ<r©4œQó¯#+”WÈU.Ž€4qñõõ;¾Í]Çÿ4yâ\×<…¼rðkÊé~Î ,Ïõõû¦|QfºI6¾¿lÛŠD#&"WâËÒÂÐ`YÈQæYcpzg— €¼xçӀŒ;HÞ±â Ûò'VËMÛ(ù|‰·á!5˜G'ë”Ï¡,îÖë§Ï³û¾m'pYfÕ7þ84 åU c$‰@Åà[bnÔ–bò»l4>Âè…•†Y— ¡ª)÷—±},D#‘üQõ¬P˜Þ· ¶Ä¼†7…0®"Äô@²c=î¬ —$Ìð*äÝW\î8ŸË@A»‘N£sÕõ˜ˆ8þÓ.p…ÜÏÀ5vaí.WIž@툽{|P ¼Cűm"m„¤,F¾xá \€ù‘—õú¶:3ƒë(9Û<Û´&é•ܤbâ (0cÿG‡ÄEi=uÌFÔÈUýó$?'›Mÿ?<™®p;@¦»ùÁ…½ß ±¢Hiœè4ÁiðM\äÃÿO°È}×ó¢Cf4G³µöU{¬ï™4JtõÑ e©áˆâœº Wäüö‹•£éª:¹Ó¨‹u1`-Sø²\Cm9[ìáTlé"Ï×мÀH‚I_4©Dƒj'QæÜ[ëCÃäÉ~È€†ojrâji³w4³ª¿¡(ÂüÌC§Á\jwŽófb»fÑùI@Ó'ùá‘ õÒAeÈ'½ÚÀ‰¡,6f7í ª™U®rOÓÞ)&(c…”ƒæÕÁ,H]td!Ææ*‚îÖQ`î ãÖ½Ôs§n–e¶çLÏýi™GN/Ô¡ï†ø…ßáWòbÇlæ·˜SÒTïA UxMÐm:dZùœ7d>œ¢Áqù޼†°‰<êa–Ò*ªF™ H„*£qêT¬ÙPqiFeš‘Ì($˜<³Ì©[©ˆûc­•{8ÖÌ-<3u!fBI^i÷{ÔÁ패ôû‰ At ‚5ôl•ò nYi¶Lw„Téƹ<"<ÐSEëB ëq¯‘4t)¤exÍ«d;{IJ'R l-VÐ}“«àe‡×3¤©ÊšÒÓ/¯_£•SÏ> p‘ÑGÖ:+á\¤…²ÎëÍqÔµÃZÉ‹Šõ\Zº9¼æjGY¯”V¾Îšqâ0ïåùÞ âN”ü¤ ?¸Èå'ͯ§¯¦„­¥6o¦v>i*Ýç‚™}ëñ+i ¼©ÑÚŽ6m#Á"²kSÖgµq'eZëÀMR¨¨)4!¡yfá„éýý«uY÷ endstream endobj 537 0 obj << /Length 3069 /Filter /FlateDecode >> stream xÚ•ZKsÛȾûW°öb°Ê„0xco›ØÊn¢$N–©8µ»‡0±%«\þïé×Cr9±§§çÕÓ¯ V«`õ§Wüþaûêæ6LWJùE’„«ín•…«4‹|•¥«mµúÅËýh½Q*L¼íºˆ½¾;Ý7fØwëMzÝX·@e‰7î wëß¶¾¹âUæY pR•¤~¦Ô*ô3àÓ¼?°Øùâ‰EÑjãˆmQ fR0øi’1ÿåÇÙÊaØ”]»Ž”÷ˆL?ÔФ…òUá),Ëlàt~„@Àñ úÓq½ sO‘'N­Gücúq@nêæÓÈýÝýz“$Þ領}»¾;p¨¢î™¼Ó0„É¡;õ¥aÙÞ{3ZbÔ#n’Gvü«ùgËÎÅöZ¶QjaÝËæQ+œ‹tÊëM[™ÞT(xº¢nËæT™©Å¿ïqKÝ0e_Ç‹!ïßÞ2q;zfºìf3 Yþ‘s#iÏô¯Šs1kjÛiüû dí/e»¯̼½>Ê…µÂá#¤¼…̃£Õ%LTI³îᮺþyGÞà©÷´¯K<ïžEf ÀËÈÜdÝHà úan}v-»»Ó`*½‰Ã¶,2“N2ÒÉZy%xÖò‘rÀB½î4Aò4r“8pC÷hNò³“~ÔþŠ…@ß|nÃ+¯ídHeCZ†aƒoYæiod¾g2‹7ʦ “¤²Ì3o°™³ýû ?®Å—pS²’ÑÃóÒaiTVšG4,ÃÍcßA¨9 ÜzªÇ=R±D`Yçrv×Ìz½ƒî´4ÃÀ¥b¿ˆcـĸÿ MÐé %.DµÆËM¨[Ã\رIÂÑ-4ñÒ™²þWHMC_ᄤ0,ü¬HA5´£Ÿ÷ݘBI”×µxñ`4Ðà@pÔòÌç êÖn×,­$0DöGÓ¯ç c_%VäÀ±ê6*ð”écDæäü:ÅV^“Iá˜é™fûˆPSLhþ©j8_AŠCeN{d`…7êŒçkš÷öX÷]+û”× „ƒ¾Ö`G¢…Ì9!˜¸¯òéŒ?½w÷Ãö݇·?ýóZiàcŽQ‰¶»®—s £îG¹YPKª ƒeçj±v°`†Vb‡4r-& ½®›;H}øÛëvhÀú¹) 肋sPnŽBý‘³ûÏc¸&Ïáh44+$9=´®ÈÜ{úÌtÃîÕ}+ŒóXRÆÒI›¥U2%¤«z86š'ÇãWÌž–ÚÑ N‚®wz2ÛSñ¶Ìо™ã¶‹¥ˆÁ'âbg°„BÕ)ÚTÆS± H±¯ÂÙ )¼‡ŽÅéâd™…x6lôН=x|ƒÚ m21§Ln4yÑI7Íó÷¸Ü÷ìï…àn0 H4¢*<‹;Fk€¡®<.8Cg[ Ñ#7»Äx|%Ⱦ„T÷S¤@«Ä¥LÖÒû«ŠânËçï\~ÈAÓ“£àŸ'¾ž÷dµ3_Y¹ÛqwÙÄ,¦qaƒôËÁzš €°o˜h©„7’‡PdÐî…d;!Õm²¬q|-£È½‘Øë¾r' &‡'±º4SÙÅDîO2(FV]Þðb#̺]„mx{dèr³ã€o··èhÌ€ zÐ#‚§8¼GàÆ´>{îœU°‹Æ{IþÈ'CB·’RPÈÚ™¢Gb³ ­‹“€Lž‚‡¶UÀZò5ïÎÖJøžS6ëëåžÖÖRSï÷Ô+î‘%ÎïõœtY וäBîNÇlүǛØ$@¬”Öõc¹ë+¾ôÚ®ôЍO… ÞþýQ?nËV©_dQމ¡Hü,ÈW‘Ÿ*9I|= ?ŽR@b³ùDÁ‚¼—â‹ £9L¶Ö•±^ЈëI²ã^R‹³KÒ=¶g% ›ÅsPÖN…ÜI†Ý, ü’æE¡.†µ‡&ÚŠa”]óEèÇéM´Ÿ'w×J‰!=‡¹•t®a2^(zr\h›Oúplà 7‰ ½;C©„†á„e/oHËðO‚Èž\p²,è?ê1¸“çói† #~^\äD¼–7b zb»`äØ(’pƒè¨Ä›“°³vm4²E-#(6ZpK”i15˜Ýl²b¤Œ¦Ï>0Ö† Lb/Ûü¿1 ¢Í‡`+îiÁ–{z£«g&ÉP¦·Œ½ w úy#ÈÇ"¹n™k7…%Ü‰Ü JMo(f¯;&ˆ‹®mdYòFmÃ˼3®ã^L¬Ø­ybbŽQØ¢Ì ¿Z:­¸iIOy8É8%´Ü§:eÁ~y²ÅÚlž;U= ûîÔT2Àæ1ÎòÒlfÈk5Ýià&÷ºz¼ˆ¦$1Éô‡¿ |•fÖï(˜&™7ÀmÙç'l[>ë „õ{Ý䌉÷wûð5Ë_G•F>7»èÛŸHG” ­ô²pÄ¿qj³€Á‹Ø¦g‚ªÖ\%üÖörDJr?WÓSÄ»ªžB?»~_ ˜ÇþΕtVøa]à›žFA‡1€0 Ýn¶ZÞ\™d®äïøE…j§$¥˜u•Àaz58{H ÚNgû¦új£Ñ*—2+™ æ­)[°›Û®ÿÈ6øÙÚR³ÿ²„U¨lb4mÙUÁ>oÕËÛéCÝ<æ4@ÜÁ4€±ïËr•åÔ~³ÏÌQƒà„¬cëógÌðÒê|€ë# £x~§êÊœCp¹=Fl°âÅ[»{Ãn=ÁoC¤½»SYWzó#j¢¯G2‘ µ¾­@’Ï•{ Õ<Æ{~%Ž?5’û wÞ5¡¥…I–ÛŒõ†ð ñ–ž÷cg»¾yË9&¥Ž“LO ?_8Á†€Bê¢#oEf¥çzÉjdé鶪é÷øÏSÝ4bžtû`.Æ_ÅÜs4HEÁÿõöà8E•ÀS鸂5óÊì4èù šû’_,îÓ0ñ‰%,¼8tØMCûÇo_rçqeÿ§“IþÖQÙOTTØÐ¼9Máh¾žÂºH¸Š§ŽŽÙ\ôAÏdбXW]LµÄàí´ƒZfm °`h,OR±bèr¶è@Zêî ÂKÉÓ¾¨k%aá”4ÑÈä*AÃ91F«¹—oî©VIrWŽ×>ÈËB‚0½gbÙ­TáýŘã4?Dããi4ýæ¯ylezY±rn3u>ë’¸ó³âÚ×jP‰Ÿ§ÑeÔv‹"‰§T¼åºÅWRøI‚rƒ8<û{6¿å)~®„ø3nâ'Q‚|'îg\æ;ì¼>™q²Z6·lMiì«lRã Æ“1?´Â´øB‚¿çWžÓ•#~ŽüŒgÁnÐ ÀÏ(é%4‚!¦o“Tð2¶ô,!Á?úî¼4±…ŽóEÒ-,¸5=Óƒ ¿øg!öÝöÕ_) ƒ•ÂïøJå~D«òðê—ß‚U|` ˆ|õDR‡•Ê ÍÎ4«Ÿ_ýƒÿ!Jž1\Šâ\ÊORuVoG‘ó‰¿Ñ'ú\Eò¾0ŽÇïonFÈE÷>¸âG]£¯KÿcSÍÍ‘êcìÙ‡æ…dqv‰PéFäº,û–ãKüG Ž endstream endobj 543 0 obj << /Length 2767 /Filter /FlateDecode >> stream xÚ½YYܸ~÷¯høÅjÀ-‹’¨cá]`ãõ1±ƒ»cl‚µ4jv·2:::2ž5‚üõÔEµÔ£^8 6O"‹E²X¬úªXòVû•·zýÈ“ï®={åG+¥ÜTku½[Åþ*ŠWÅÑêz»úÅI\½Þ(åkçC]äÍz(gkàk§7Ÿûõ§ë?>{•¬R7`%XÁ[mTâ)Ͽگ;÷k?qš;Uv‹]ýž ×Ê٭阒75Ž÷YQõži´µš›õFkço&ï…¿¨ù[fõ~Èö¼Lä4ýÁ´2û ÏËz_Ânð(ç­§x&ŒEÀȹ+Ê’Ùkc¶²DÃc¦FÎV†£ÓiI{|Ü,Ï ËŽÓ trä>dm–Ô6 uê4í8˜œ‘¦ÈÔ6wäÈÛåmqì;é <•{™P_·ÆÜâ‘ç¼A]”²ßÛ¬Îζ~q(jÓ™¥CÌ¥r×›$RΟá"ÃØ‡»Z˜FíñRi5Œ®'ías`Îô/SÞ±ÁÄ«ÈMã Aƒñ½ÀõÓ•ïz¡Ï|ÿЪB7H¢ÕfÂtM¢kWé*é_Žôp5!ÿE„»ÓúÌ{øñtí† “Ç3Þ~TAø¸©‹ý‚8Ê Td9Ñ4pq{õ-wÇC¿6mÅÚ œ;ÒY»%)Á `Ë4ë÷}û¯µö<w 7ç'©s3€øqâìðý8{o÷¦eb;Ô·š²Ç ¥èŸÈXÕ´†GÅÇþAŽX"ºÌl˜{rìÚSr8¤düaÓä¡n8±g$@Ú .sϼb3‹ÞÓÝw½©Ààt¢Ÿ]6QÎ/h¸w×=yxⱆ±ñ~ (¢3ûìËÄ—Ò ›§>¨‚VQc€Dˆßׯ6 7MðÂo p‘Hîì<ž]'cJߺ¼çÖ!Íó™€BØ_Æ‘Ú ­?d(¸- Ίö™Èùxíz[޳åp«€eT¡›†á\ñß“q¦ŽÉº{lÁ•6åÐM jÓJƒ(°D”ŸÌ¹É‘™í[X_á¡[СˆA*fµ€FÖ;¢õlµ»C1‚ÛÉ Ðizf€S‘ó,$+[“mEÑt‹ˆ¢ÏÄÈÚ-÷(M]ù $Š/ Qx‰ô ‰6é‡ãS‘Q®Èš@¶ÝÚÛ3•ìã ï’RFz<—ć—Õˆyu³-ðøŠÂO%ݼµ«öh¬±ýùˆÏ¾ç\3„À€5yÎÞ…ø'ÓgÖ yl4o~´qBF™ 4Š:/Θ`!L¬, ƒv<æ¥ç~ñþ‡WèCðVz2‡ H —,ú*;Ò¶¡Çy’'øÌ€O¨اSÜÔ6g€›«šçÙŒ Òãl26%bVËÈ0’²ÿ2Ú$ÖY¶û¾{qß>¼¿ž©oïL %½¥8´766ÕçI®)K¶. Áã%²õïî$çš˜ÏørìòûvÁ›F ˆ7b(<Üà†*|qóܺ/@¡‚Çg¨’ÿSÎÇÒ‹“axƒ #:e!FdØrT²§ “¦sÎSb HXPt 1ÔŠZÒIhaŸ 7#Ï®à-< 鉪")`;–W=o¬!µŸaJ×eèÈöˆat€xMpƒ ŠmÀ ,ðÜÀS— b~ ãžì±¸ekþ>TBb:)QD!-Óø=$dyMøJcb¦•³7_IJ[Ç‹—^lÞþȃ'vPB ÈUòÏ—LhIôŸž»6‡RÄ1µ$v*9-ÊEqÁ¿âC g_Q#\O­"d?›@0á«(áãõUÈ}–g> stream xÚµUßo›0~ï_ª=€Z0ä=tUºvZÕJË´MÛ¹ÄI¬FØ4Iµ?~gL²t{Úòr¶ï×wwß‘ÀY8óî$øƒ|;9]aêd(KpâLæÅNB#R¸Íœo®ÿO~ÞÉ{Hè‡!ÊÈ.²çLÜÛ•y«´,Å3ÓBVöIÔ¼àúõPÏQѲA@òß ö‘ë†Ï*Ùzú,eiá¼±" ‚—<ÔR6:oµB¢R¼ÑSÍ×zú ×çÓ›Óó¿{—rƧª.DÅÕÐõ¢Ðg—º)ÎnNMˆÑUº7Å0FYCPxÂ}¿¿ziäÊÖó£(vsV™q[ÅíË£‡S—o<¤dÍÌê /tuîù¡Ûš“²Š\VJ(-ª…½Ë¹Sʦ¨—Û$²ú„B/Ýó>~››ÄK{cÊÖ‚³½b"¢ ¥Ð¤®Ž®è/ç¸<.=¡G;cdó~‚*MŸý8ˆNÒa»sY–Lõ ¡DiŠ×¬aºƒA5ÃFÙW`†R\ýlëÞ]Ú÷¹l{bM@µum›Ûh>CžÝœöÐLL"œ$À~Ð.ÓyXóHÜŠó™²z“ËH;2nõuÁr>³Š•ÐËÞtXÈan°`Ç}ÆA†’(ܵ®_³fe(&;%K¾Zò¦növ/±%¶~âÖl é{@;zމDž$E4I¶Ù>.åj;FŒh†Æè˜]õ=ãt.öSrL‘êÜQ„-˜'WH’¹w†´8S‰µ!iJúÙSâÎDÃs-›M–v.@ÇÛ°¯®ïnÇ#Ÿ°‘ýŒ©c E)Ͷ+Q}i!T"çÅÆìí¶Ï¢ ÇJÙˆ³ á&mL_·ÑÚ…½,™Q=y–7ûÄUfR¾óª³¬J{î-ž<ÛöPô¿¹Oî à ³ã“ëŽæ»¿ EIHŸ„vÚÂÄÉÀh<9ù‡¯ endstream endobj 552 0 obj << /Length 2499 /Filter /FlateDecode >> stream xÚ­Y[oã6~Ÿ_áíK VEIÔ´H;MÑÅ.:(lm‹¶…Ê’W¢“É¿ßs£,9r0˜Ý—ð¢Ïý|d¢Õn­~zÉøýûoîãl¥Ò0I³xõ°]åñ*Ë“PåÙê¡ZýÜݬ•Šuð°·7ë$×ÁÏGU ³?"•6Bo»þ`ÜÍŸÿæ¾X•a™k`­Ö± ‹X1GdÈ@gy°1-Y0¸®—µª£›ÓÁ¶7@¸×ë–ÇÁ>á²íMà È1:ئ‚¡~l,³d†UHupwèÚÿÀíí)Ó[¾i+ÓW¼üñý|o+Ô•P*,µ˜å# Ð nØôõÑÝÞ¬Ó2 ž÷õ×÷0ÍV ‰G¯0Nzk*¿ B¿0mHQ?9›zc\ݵžÓÑV8é¶2ŠÛµÂ•á´A–r<»f ÙôÅ73ðx·é»õL?Íú=‚#{ü âÚ˜ÄeüÆGV[™w=oúi¦xªí3˜:K8ZGg7ã07LÄÕÀ‹µ¢ÃÏ­¬¶ì7Òž†º>ä$Ð/¼2ó¯‰êá’fÈI<£=Œ˜ܾ˜â1…@lít% ÚÎùO1j+Þ±·½½e’dÄ͇é1ìp¸ v–¿‹]™B˜ÒæÞ¢Û8ÌŠè~½}C0¶"E!‹Ë4}¥mOé± 0²NYt=¯…³sRGÁÄ$w Ny)1N„<0Aç#á(úÕTœáw(Òï$ÏÂHzºÑ:0uca[#?2²£ö‘X¹ @R÷7Eø3!¡¶n(+bu¶!~#"q„«d!ÊÚñ‡ƒ šº"#ÓÉíõȘ„2˜ëUšòòiÀ¢ <ÆVèGè‡ù¼w)˜ÅÂüÓ¡iê˜hh‰ëõJå'GƒA†ô{$×®[×G2Ê·~KÛu'ùñû-„¾}Ý0Gµ&'SÙBÓ:ð€AGí°†'`¹ ôàXQþ[ñ—GßS’©¿qF±Ž[*‹uÓ×eþ(¸i^xf$ŽìÜ1Ø$ržEÁ:Ûxqλå,Ê\‘²rÕsÜ/SL¬¾aÒ8â&Rª#_³ð“Ûûý|PÚ¦Ë32Àzˆr—ñÔ$ð¡ÞµP„äç üÂù0¯ÝŒ¿¾vKð@|uãVj W…²¾0õ\ã!HMêdô2¦êíø&‚™ö <ü‘twâ²Ù™ºe’ê Qc÷@×Lëÿ\²MÕ{ü¹aA1†ŠÖa€‡\þ'Jñg‡+ÒBÕ«ØÃµ±{ÆR´qFœ°j?m쑱ÁøÉÃ,”TY`•®,‹¢<n‘­9Ø%­À‰½“Öë%Jƒ?T’~ZÅËÛÞÚÆcˆŽ7˜JàÀ¥|txcf4©Óx.¥PxµÝßaFÄSâŒ30>7v¤ 0ÖÒ͆!_ãgûÉlU€˜!U©YmT¥#•ƒÅèì÷ËÅ,‰Â$)ü¦‰˜¦1 /’Y”~ XôB½„CA!Zº®Õ˜8BȽ‹"3U4É&ŠâdYÑ¢µÒS=ò,(«uXKÊ2{ÄÅ’CIË9âqò Rlýv8¡’¿€ÚÄa䓜Øt¼‹Â•I‰Ö,’vy¡Tœ–aªâQ«ï ·-h´NÊ$,@ûY}sf'wŠ'8y@Ø÷ÂA[#ÒmáÚ=ƒaïj±X‹Ò”bxŒü±‘˜è œ†Lk†N€õ̵øiIí² £<ÕþÛ‡_~xø÷Ç—™Å£ÛAeÎ;`]†¹¾Ì<,™(…=£]±{n Œœ-B"6ÜË麗3Î)ÄøÐPM®çô«DO•)ˆÜx!CçÌÆir¶X]…g4 ˆ2í1Š0)J7¡4Ÿ[åXJBç ·BsĪ7Ý7·=¤nš§^"Ì›ÞþçTC Ñu‡n|“ƒ+£Óæ$SÜ-÷2óiz÷ìåcCp'mÏ#%rÙ!Èš•cì5ØžðKB£±$’³u[!÷7çe²¦oj‹åuz¿B~Œt¨³|Bò¨1p?(3D8øûR^Ip©–Àé½u~—åM^¹/ˆ?P0›äoçæŽTo·Ü‘IÇ<š_'peéf*þž<Â?4KÍs® øÆô;ºsêLð[®£w\’öˆ.Ê”\Ÿaùœïz"µ©H­¯H­G©ñ"ÑûãÍÖƒf:½&@þðó£Î‚‚bL¼ö{à•ûŠå¤,=NËØCˆë”g|8à;‰..¢.±|éÙ±ïv½9p¥œgÎÏ:º¢Bt¿™q“&‡&èg™F‚=š{äƒ=R^4¿J¦ŠïÅÕÅæ±’G‘¸8’Ç ®Y {cçˆÔE‘aÓ„KEK´[ÇРKqÞà,[–‡á ã¨8Tù…I/¼°ú}­A€»Å^ =GO€¿%¤”†y”,ƒÂ~s—Ü·Tól~iŒE\l‹*Œ’s££›Ãã5ˆ“ÅéK™ga¦/ÄL®ˆ)IÐ×VÞã½]—a¡ËQôÇÚÌqAðT‡*Í+ﺯ m˜äñg"½e3 ŸgUDž‹yH¥ÿGCÍξjCœÆKb ¸)Àõ…·‡…‰Â\}.(—/›Jçô–Ç”‘ú ·«6¦²_Q/¯^šÛ SN—ÅWþŒÆ nÙ»Z•ÿ“È,§”t¸sɾ*Ö:Ô׉žw ××}²ÍBB:ûp¼ú t0ì­Å¦®“<ø×žžˆqõe‚oºº,§t¡x·*ɇó €éSݸu-wêó¿uxÆÏ¿òˆ »I9aë<3ûJ¶ùÛ»ì@K¶ÀRÓ‰¤Ýd#Xg¸®£+h=I³¥61ã‹h=R—h=äÚ ø\§ùãsW;~¤»Ò A%oà„k¯®)³¾}»0÷Yù1'·º$E¨Šä‹DÞ Àþ¢>« nÇXhŒ…o§ùlÓïþ I zÓ endstream endobj 564 0 obj << /Length 2479 /Filter /FlateDecode >> stream xÚ½Y[oÛÈ~ϯüDÖ„oÅ¢@sqݶv ´EÓZ[l(R%©8î¯ßsŠ”(:éC_ÌÑápÎeÎùÎÅþêqå¯>¼òOžoî^½¾ ýU¦²XÇ«»‡U¢Wqª _ÅêŸ^w¸¿^ÇÆû·Ýô×ÿºûyøôõm:úÌ*ˆcxA}ö#¿Ù÷eS笃ëu†^Ñ\¯uêm;[_âG²aQDnNXLD[ “u4-ò}¹µgŸŸðÑ´E· c(Eÿ“Œ_p\à\–åF,gÄìöù£ÝÁá fa—„ŒTà/R‡‘×o-.b¯©«g&}½ æÕÁòÏC]ضëYþ[ð›{Tá™?ÿ¸‡gâÉa%Ùîõ­NFâY¬"ð ‘çáPUݦµ`Ú;‘\«ÐÝÎ8DzÚ–ä¸e›üÐÙîD‹s›ÃÙ+,S~bÀŒÊ"1#ª„÷tOŸXþÑìùWm &”5_ŠËšÖ;1ˆåM¥?½»åEks´žZ¼cmTæ'Ó;y2,†Iœše¤S€ÆÒõåuàí®×SöL܇¦Ýå9´ÝªGÅäÏAhÞýAû~è:Ѿ |ÿJ½_(Ý$¾œÏ–ŸýÀ,ë–‚ç¾ ›3=¶Ô AÍÝ¥ëpú-Jμ'·Q#$vø÷žt°-áB$¾JütA?óÊ~’ûâB/–У÷³aä'*Ô™;ùÙvçñD*΂Qü„A.5Ÿûq?¸<üz*ɳaÕå3_¯ïØr°8 ¬N>Fw*{p¬-rñ½¯èdQïaUY&£¹8ƒ8U©¦±Hg‚ᯄcÛI@ŠóÚÜ?Rñ8Åç¡Öáôºî¶¥|m+K'Œ¾à5Ĩ,¾w Evûž- =ÅFºFjÀ5t¤ÒLœúO Ô "øÚ™ ‹š†ÚCLîî+ûÇQ¬= ¤îÖŸ_1pL”‰SX¤*̜∃™ö6 +}¼,¤6üìÉ>:;Ú‡²¾*e럙c²ŠU–„)9U˜¨8ˆVZù&åÏå2*LËF›îèž"…h:€‰þ~ ã™ùï,@×Úe)7 ÝSaÑ“ý€÷ È? ¼=ö²2MÒÿ“2tçx!.$PÌ'ŠG|Ý꺬ÙŸÃ@C:ˆ¦ñ1£V±!ñõ÷ˆ¯/ˆÍ‹ ⃋‘½ñ¹ol×É41-ì·žWͱ“MÓÍg`y&5©÷QŽè¶Í¡*$”²‘B°#‡º«nf€  âäN†|&@ D]8|‚É®hH¶~SåÝ ¼®C(Ë2(e&w´iv»¼.n¤ª8ÆlrÉBcYf`äN°ŽR€GïóÍAΩ±¯ÒÈÕ$Öz°bÖ»|ÓJ‘SXL“u‰)¨S‰#•tL´˜Ç0 é<¹aéÁÒ >A0†…Þch|º¤(Ô¾oK°Üœ”³úXÚzÓ4g…Qj†}èZ~è}|` }¸rÏÎbÁcÒPüH3Ñ–EÁwÄ[|!Þ¢ ñfNã øãUU’.ï+“žºšT‡®¨‘únk'žÆ‰¼í†ñŸ*$ VÊ®¬± Vª ;qÛÉ3.šØ‘Rl½q•Xý8—6ýó„þH¼/û]¾ŸK—Êœø{Ó%”M¾?M—ï]M1ãðF%q:/C:!ˆÍ¬¿£™$쬋LÁ:M 9×…p.c2dç¹pHÀ#-èOåpbFÀ–á àœ±Bë»Ù2G§*‹àäÚȰžÓÂox\~•K¥=ÔPÑæ .níek iJµ".Fõ0þ<oøë˜ý5ã‰Ös Õ=¶ugå=¿â:iîVN¸¹kabÛ!AÂîOöËg:ì4™-·¢ÿÄ`OeÑol†*Öæ²Í¤—Cæ¬8::éóöå7[½0p^ù¶¶|ÜuIÈXùAðƒBòÉ.^ŽÝöÌN¢›¾ 0ótšo›ªiƒä¹4˜ÑQ¼,0ßtÓuå}%±9ŒG\L·Ò?P—l¿–û¡¥FêùêfÔ?Ó›_‘þá jå^J¶ïzû—ürµ¬µ?¹¦7eß}¢Vû¶Ùí©Qmê$^ I‹ ½l‰ÑTè…>*}!„ÛDtº°_ìóÒ4Ké…†:eSã fFâÏf:¹¶ö[^Ø `f…·Åð¦(qˆíà\ Ÿô-¸b^w{¸ç¡‘Ÿ²,4>úÃ~í¦N*KO yq¨ö$yŸøHÂ_¹\^¹-:4*{óýã$ ˆÊÖˇ cŒTWTôKÑÚqµB%.1€•KoÛ£ß EÉÐâ'Î]ÚiUÂãÄÞvS2%6)bó> ÂSt½-Q¢%Ý¡áZ˜Ô˜ 8Å$ ¹©ãß„¸À›¼­ >{g]ed¯øÞ¤ÛòîíÝùê´à)î('æü€**ï®ãÑÙj*? §î52*"Æ7ˆÓÛvzg®È0G'üùÓû#«wh€Ÿ]rEH“>®Ï/Mù2hÁ“¥YtÀ~4’ŬѦ÷ygcsŪ¬ày´%Q©à•œÑà0ô0!ʱ|äúXå:ëƒæ&ëÇG°'¤²í5Í[ Ç- yã^˜aÑä,ÚFAŸŽ©÷ÔçÅaš@c÷]Å«èùâÎ&n<‰1,9á’A£ÉsÖbyeYž‚À‚”ITŒ­Ó‰/ã\2Êdl \¤}ïoÛ’î舸¦†4À{BCñˆžÞa%ÊX)|>ÖˆÂr(¶‡H%ƒŽ¿Iy¬)ÿèØÈGRZñv®P¾^€¾…FœDC}ý©¢îÿ(è-˜m”ÿIʃ§ÒUq-Ó;7-ŠiS&íÅø_N÷q–nu‘·Ç!çÊM5Ç"ýµ¡âÄÅ ¬x-RÁÊå'X‚“Éë¼eOÇ5, 1ºì׳ݒHªz;ÌwOö ÷îä¸}Ù>ðj¾CSôÊlnp;ÖugépèCٱχ)5ý•ů´q•?ÙDcqTÉÓÏgúß·Ò iÄ"a ´Áž@{ÂÊÙS²'ÅÏ i ¤ ·ž…#9ì ‰Ó´YCàs|‰"ç©Àµ1‘÷Níë=$NÆ.ݸüî^<¥uù{BиlÕG„‹8½èNY ™ËŒ¸vå­¢d0é7µ“hß0}RÖG§“Mïï^ýŽ™´m endstream endobj 569 0 obj << /Length 2057 /Filter /FlateDecode >> stream xÚ½YKܸ¾ûW4rRnZ|H”cÍÃÁæäзÝÔ-ö´õ#zŒwþ}ªX$%j4mO`äâi‹Åz|¬nž6鿝R÷÷ûŸ¾ˆ|Ã9+³Llö§›\KÆu¾Ù×›_“Ÿ™Øî8Y²?›í?÷ûôEfó 9g β¾WOæ'â‹+Îd™y>Óš‹¹n%O'4Ý”¬Ìaðîx*X™jøQÀ.§ÉVŠdºæ0¦Ç]ÁøgÇsV–šX‡fhMÄñéK1“/2–¥…×å·4Ko÷¡¹]«~óíNæÒÉ€Ÿ*¹éÜôDA+‰†›ë¦¿·ÕVÉËVèÄÔ´T Ä\yN®~§5•´·íXK¤æê¶ÑçéÖ]H‚Lú;p‰96(ÄË8ЉN5§k?X*™¿Ù¥,O98ÇÆÌíÏÆ hçÇ…‡â" rî¶š£Õ÷mÏÊ’e:{Û³BÊd€JšaËt°ä`ü[;¯ Ãëü0‹Ú  7[Çá®~¨º¡¹>Ñ××f8/… i.¶Ý)Γ_ÜQÖaÈUyH¶ÈäzÜÞÎôN…äS®Xž±S4¸ôÐà"9‚‚` ¨†»GÓ™BÅeð¦ý°›¯Â¹ÏÍmœIE ¤¶ )p: À%ƒ£]æºE'`¨cA:¶çm–%U;fÒØ2+ ý„Š‚?Ìå>xàa@àìëÓGú•)$ë8ß/œ0k-mp¹BÏ@ÄKÉÒ‚{…Û¼¸Ä%SZz¦YQ0i­’±··)×~0U;zmÑ£~<|øYÎ ¡?/’=¥üiŸkB|‘ÇËsXžIßÄáËA~ì(Œøá1"$¡Ü®»ó¬{€Õ(Û…@·°–t®ãà/”‰éD© uøåÃ<Ǻrçã¹Aøm01è9ÜÕdJQÜçœóH+²ÃnYÞÓŽ ù„Áa`Ÿì#ÈÐe tE@Ó ë*`].°® ëÅë¸v¯Á]d)+¡Þ~ÜÅ…»L3&ÁAÜ/U÷o,µ ém¸+ÁxÎTPÌóä—P-ƒž’ÎÀІÉÜi ~ܻƃé‰(ãµ5}¿È,SÖZ¤”ÈsÜä&›Ü_»_*ÅÒ²ô¶\o¯}ÏSëÇÁÖ:YæL ÈÐ[ˆÜ5O@`ÓbèOÿÀ¡ªuÜÆð8z›_wYš&?;Øy‡¯˜”kV¤AßÏpÅMÿÓk³ X—R.Z²p¦s¡ÓLKãD¬jW¹Ú´vëûæÐ¾Ìï“…Ãüg4×㽕:  -B7ñ¹­^L÷;úW† ‘±!òÿnÈsc¾®Ù¡˜N¿Ï .v¨l‡½2¿ÜmKæ.Ðí°ÝÁ­û¤r× Ì”´ÇoӹDZ»˜Â•´°’™KHðU£‚lEkpûìʼîˆás§ò”t³IÄJ‡tÌͱjÑBKªk'·"BmNÕØD gáŒkuÁŠ«¿q©ªö~®þ0µ}¥R®¨8Ëžô§ñRíœR7Cuhmº‡üF~‰¶g“cìÎežŒƒkXzn®nz\K4•g/ b ©³5¾ÌA¯lq»¾žMçUn[bŠ|á;¾ÎK˜[úÁ¾‡¦…ò7_ωÞd›³0O2Že–Neœ¼`PTùjòŠÄ+HÊ’/JáÊ"ž'9Ó:ž'÷goÊÌD8Wnåz ¥dÖbCÿƒÍ‰‚Ûá‹üzé÷•¦Cìš|ol~÷ášÅÙ;•Xƒ%q*jwca²îóôµ·Å{¼=O±ßïí…ƒ‹÷Oìxñ• GÝuÙªéL=µG”¥N‹Æ Ñ­=ºCè\+‚Kc?ø€q@«æêoMã»­þ^Í7:+R8ÊϘ=J(&ä£ÑY¹–J¨¨wÅÏþ|Ûšx.)®”!)ý¡Óy1ýJ«S@Ôžð·" öKŠSaÓ"*Ö\kHÎܨ3¤!PGkƒ7 :ØŽ~±ǵІõ‰AØ…§º9½8ꌥŠ/Çr;%äk÷¨4…äÓl±( ¸fãKAÔTuð‹ôuŒö„îTÝ¢ âÉk0v½YÈšv[kíxÓ~ÅãI§çÜØ ð|ÆÉýûÌ05ÍÓÜᓽ¿Šˆ'*J; šŒ«õ~õÖÄ™²H\ý¿ØqÏßžCð òbŽ 3T¡¾£FLoŽL¾'kÍú©Hº¡éÛI ZöLýï9 ü¼/vVêõöpír)d/^:¯‹4šJ>s0,B3&¨³ŽYßDzG*_!–°…¨èI­'¦Úà{âÕÎŒði¡]µ-Ø‘`©޹WÜ^Çë­ ˜|²øâ½/[®½5VÇ¡y¶¾}äYÈ™ù㲦ХGl¨†0Æ%ƒŽ÷¯|½Û=ØÎг´Ù7ê‚U8. ‰ î=åoQ„r¥AdIÿb1CwñÖ6G"Û k9íÛ“°=1~>uÕýÜ{"mìÚp#j¸ØH¤G$×cGRÂ?¨ñþBjg‘4tÕµoPc—vr˜OOM!íL> stream xÚ½K“£Æùî_¡ÚªŒ0MóLR©Z'^—sHö07ÛFê‘HÈ€v=þõù^Ý4ˆ‘Ç[I.|ýúÞ¯&Ú7Ñæ»¯"ùÿæñ«¯?ÄÙF©°LÓxóø¼ÉãM–ëPåÙæñ°ù!xêíN©8 ¾¿lwZ~ó4èž¶»Lÿ2û‘¦1gÓnaÆ8lzüû×t´)Ã2ƒýaßh³SE¨KÞõ¯Ýùܵ°°ÐA5Ž}ýt -s¸ÑŠ,LÓœ—4ÕVÇÁ þ˜~6óë…wP\†Ji U?FiÔ]ƺk«žÕv—dQð϶y᧪iºm\ŸñLj˜áÿJ'cwÙ5æ 7ïdhOS¢}xPã©y°fâYÏâ¡CÝË=ºn‡ú` æXœ{„è, ó(¶”üùRÍ_xžOïNgEXFp‹¤È³E€õ‚ ’(x<¡äÊ2ø´¬ªæ*¯u{¨÷r^ xÝÆy0nÿ|ª÷¸Ï‰_A ðòBüè4òÎ…O1ްN‡ïŸ+œìAâ\CÝZÒ2^›e¾@§åQ¯5“ßñ›,Kƒ¡:Ë>) ãAϪa±âR3Àçæ\ +M“5­È@ëTÒ Üvä]æÌÀÉÔv @|rÇÚÒ·@ôÖA=ò¿c3¾&>á0ÈH¸„f'ÐðÁ ²-ª>N˜×;Ìñ˜v¶“Px~×/Æ湺6£ìT5—SõŽgÊ.Œxæ.vqJ“ÓˆÅôŸ+ ÿ—;¶¯‹0Ô붯Ó2xÌŽ‚Áü|5íÞð[÷̃lO€ÞT ƒˆ™×3þ>1›{´pÜ`.U¦sà5OL­úŒü;'ëQŽ.ÕÞ¤~¯z³&£8µÎíæ/f¸å`ª 0ùç;ß)þ¨é M¾çäQÉHœC:Dûa湓ãé•<Ì’üpÇ[Å:¼_ œm-.§®¯íXn`_/[ÈZ86A¼‰Ã"UsÝå`¹î«–Å~¦$ã“„šÉ©&“ãäÁ~ÇÐðЧìÐêUÀ  Ñª=¬q¢LÂ(µ„~ºexÈtæ!ÝåÂcŸåÙÐãŠk×Î~)x:È/0±ßÐaPš”RÏ«“×s®m¸£Ï…ËøŽ>k¥[ÂL%3;Uˆý(Q^g|¨[+ûgœ$¤Õ~ŽÇ&<¬;<n’d(“’úÛÅi˜¸™c¿M!1i‡f’ÿ|ç4 SíÜH¸R\ÀYYcº[«\Ù"£¡¨˜QžI²·ú¡1f‰ðö–ðœÑd&Eâ"*ï«™nÁˆu™¬P8”FL <¶‹4¼x¡´k »&p[‘VÊŽ~ZGì-`‹®•qJXà%Èù‚ <Ó¯ƒ yv¨H†“1¨ÍøŒÄe$þÎöWF^ò‘Ó eWD˜{hâÐ`dLýžšŠJ‡¿“z^ˆcPVŒæœQ ~à@,®œ€álJLæ ØZB!cãTÍdZþ‘ïŒFâ0`U”ÆÕ4›¦ÌÒµœ àc_YsÏ1 ’"U¿`bqÖxêá)’Tp-©ä9$é\¸ŒSÁ‹eý«ªRž®&)N)ÌŸn•9 “ØYú‰Õ%Qy˜$‹¢qF§ŸµôÖSÄ®@SëÙ8=UWƒ%ŠÅˆß ˜ßÐÓðÁ {p ’Móà•RT®dWÓ×vC´>„¡í\¶zÁj&Æ9qÚEɈ8)Æ>×È +Ggõ6=:¹M ›úW3,j½û Á¿â­ôÊÙË$NœßnvÉ¢°ù¶r-T„ X–AÏíÓ ¶ôµõƒÅ=÷q7+;Íc¨—b¨dѧòºNàÞòÅôyýO®28¿!Ýò3Á±C…7T®R^³éÔ¾Éødâ¢?2¥¢AGkM­ù,\¿>¡PYXª¢ø]7o ¸©[P=š,®v¥§Oh1#´:Hƒ´«ª'5ƒ9zÕ+êg÷ÿäÁþ <Ø_ûu‰ë7HÒq"µœÐ…Ðâ®O”BÀŽßàä£XoÑ£™_kÛä.(…ßÁˆì ñóñóµ:€12ˆû+|‰ßf í†_’ÂúÉžößdÏ—è‰YcO1En$Û4M}ÌÔ¬²Æ’S·ÀkFRZÕ€¹ÒOÚ7Ý`$Æ à¥ëA= ÚöU8)&1„Ç÷%Ùßð€yNÍm±Ò¢E/}®ŽÖ?/‚ǵ­¥K¸¯û}ã Ó/²Ó¿F”òxCçI‚·ž9w_¼,ª/—nµ&]PK_ºU¿wzOŽ0Ž'ÙÆs»GÄi ³n¬!^w—ºMˆc–(Ì#ѱ%Ъ=mP›!Ì,X0É8Ös[q'Ëè}—é}³ø~欧žƒË¬ÿ>ÖìÚ)Z ù[Å%Áøv‰~‰;[ɱá˜ùeÇ!÷JàS¶š¢‡PÒØ…íJr…Yáº6K9ãÎkÑ GI¢ iþý wj´~—è€3¾Ù1ºüFÙß-ªq’C©ŸßÁ¯×Üø¸ß›º¬š컆O¿™ø Á2[ÚÊÞøÞ~E=¤ÞH¤¤8½*NtÝáwݨâº6c œØc 6·Š«]ïãæ#®k>¢Ìg Rç²ó,ðµ ß_Ñ®< URÞ•X>€7|‚×”+Õ‘x‘<ç‚7 fȹx‚~> stream xÚµYKoãºÞϯ0îJbŽHJ¢T¦@§®ººéíB±™DYr%ùfRôÇßó ©‡eOr›˜#>>~ç;L¼yÚÄ›¿~ˆÝïŸï?|ü¬ãM!ŠLe›ûÇQ›Ìh! Ô›EŸ„j»“2£ûg»ý÷ýß?~VfòE&…N2ŽìÿXË'û'¶›œÄ"ÑÒÛÙÚm³Õ*Ðv³“±Æ(äBnrêºêá<ØíÂÊáÏN"É ›>Tñ<ÍL>~ÎÓga™?ÆiÜÙÿž«Î ,·;-eôÏm®£²>[¬ª¨ê¹¹l\½Ùª<ì“í¸£³¶ëªæ‰û‡ÖÙsÕ-‰šöÇX&=„‘œå%žÊQ¤*ÊÃ8Dg;JD‘˜ ¸ÀùŸÚf§u.’4Ü$LògX3|³?ûïÎÎp§`ÎØôYá\¤³ûáððIRä7€ÏTôoÏ×:[ÖXÒÑWg¢¶;TM‰.@­½=•Tlþ€ë~å®—çj°Üܟʽ½ƒ²‰ hC,¨#Â!¤RN«e  /ýÆ&f“‰Âè-RØxÀ¦„råhÀ׊ÍÄæne® NÃOôz9Q"òü-™7Ì“ïÚ‘úýv”þ‚‰Ü¶2ªvΗ£ ™:_vޏ/¾‹ZÃ%§xÙ¢ópC{:‘§·={ˆFïêÛ¡Sé$j݇Ϯ—ˆŒûÈ} é >ç½s¢; ^nGÏ êžÆUqWáξ³3Ø4mw,ëúÕ™€£l@Û×mžDb»K’8ú[öi¢í/×pÓõ< ×¢Ù Y¸“«ˆÚ£7V9zD¦µ?Û‘lçg§‘Ž[zævkýÒø³‹…Lôœ‡†gZh °–=]Û™LF×bNlVC΂ò¥ fGÜø¹ü,]÷ÊE@ ž°eŒ9T'ßHõpdj„N“7v vk„í¶ûR ÏãD´$‹'ÿmoOCÕzøbpýxAã°Â•…)Øà²êp¹"‰A1XÐ9%ÎSÁíç!…<žÕ5ö‹nw(„@èÆë[å×J÷ñÁö{ÀšïÕÛÛn-.橈ý˜¥È5nêRŠìtÂ7s§Ra 8©£ß#uÎýªÐQP4ׄÎ|©»F”NôäÅÈ+ÛE‘Ë•¹óåÔɺ$Ò ½Òs™®>ü¢XàÛ¿ñh8ÞÖ܇ÁšÄ”‰û qÔZ0L³è?ú]ÏõLääŽ5óÄyÎÁôUûê³µø\ZdÎçp93¹·À`—Æäò3×ýjWȠ̓ܭ§ˆó L+ K@aBõöAN¶Y¹d`å8ùxÙÖ9£õÕÿV¶rJÞ},¿n}DJ@5½»ymCÑC£$âk™Œ×’;øÖÑaãŠö{âÌx¥ý€(¹ŽvÿY½Q\/7ÚÝ(óvýî._ƒß‘p˜F&7D$¬0ðÅ(¸ ¾¦³¥Ô"•A&m½ÓLXgêâH}ÙÒáJªƒ«ç3ÀI¸Úa¾¦Á/‰q¦ÂaÅM. Tt6—áH³ lû[R®TS[ ,eíQÌ¢lH€C-¼`㜭¹X9ë`uròÉÐD^¼ühÙÂé|(ѦÏ`3!!­ƒ6‚ñÎM\4dÚŒXø 1U™E±àŽ{VÊåzÊŸ 4ÔîHJ4dÃgŠå¶«žªY¿×jížAïB6rcÿÚöHXz©ˆ„úXžëaºÂÉè<µxw¾F„‰7óæ…K§ìyé* ð‰xïoÛ!ÒËyÒ¼,‡ðÎÄ©—2#d‘-F|G I—÷ýØ2õqì½F}Z¨üºÊòg“EuÕXnx©¨È±8ñbìXx±q숅 \±‘q½eG Í?mAWñÍë°u™gãÑMÔˆ®¸ÉcAfI4 QÖ?¼j3%×aŽUvfí´žÚ¦±¨„Ì©|ð ®98Àþ `± Þ`Z®ŠHýahZƒžôg²ÔÍø.NŒG ¨M€ÓüiDÔ¡&¦5<ôm ÒÆB6—¦û²/å~h;¢øt•fƃ’+o+°NPšÙ?¬Ca²Ð{ŠK2‘Kyù±š`$¦ø~‚‘µž`ÀÂ'96²åôµÄOÓ׋ ™%"Ç=S“%ïÉÉûmXKÊ ž©øúës‘‰4ùÅÏ¿IDIØiÐâÌ»¾óeùRr¦¹«¾ï»[„.Ç´U]¯œRÜmRpÛ˜ñï€{u,|‹ ÜÖðN}öÕCí|èvUvÞ ŠÙíÀïáñ±.¶)\ÞµŒNC, «Ó°Ùh…У—«¦:áp(h/óƒp(f¯ × UhÉo˨:õl…Ç6¼&B Gþ¿çLl(];Û‚ód„Ô©k—=Ý4Ù*ÉÜ4 £L’¬b6¾–IâÉ0_ÐùÐ@\qžÌl;q2šB£ëj®¥DUNåizDï˜…Ó .Ô YVÓy ´†^)âÓÝ£D›ý«“O©÷C‘ÙÀYº;Á_¹Ï ñíÁuLž­z'HÀŠ ´¿†˜“ìK0I½jóKHinÀ[¿îÜÿûï(ïÆ϶zz!ép™ˆo% ³ 2´CéHž_r9§Ÿ< ûB †éó†ŽÜNÞ¸7^âÌöô=0¹~ã¶x°µ·==àù Íâxp“óm@þ¥E®áPð%+wÏRZÎŒþrÿág ‰År endstream endobj 502 0 obj << /Type /ObjStm /N 100 /First 883 /Length 1732 /Filter /FlateDecode >> stream xÚÍXKo7¾ëWð˜Ê%‡ÃWaÈ£NôØ)ÖÈA‘6‰GkÈëÂý÷ýf%ÇZ­e®årÐjÈý83ü83$×£ŒòÆ*6ÊZ«’üyeÉ(ÎAÙ oYQ¶øÊ%ôÙ¬˜§8ú~4ñLTÞ²ŠýÐ3Æ['cDÄè1Ò½vF‚6kË©ˆ³Žt²n«=¾6)î±zCä¾ÜYpgÍ>Ü=_ÖÓ¶YªG§çuÛà¡¢6Ú?îÜš_ÎêÛ^uƒN›Å‹i[«Gèø­™_Ëk½ÇŸ§óÓŧÎ{ÏÏšåñùt†¹¼¨ÿ=ÕG/ŸIw³œ_`æQbÁ¡NxúËf9Go»¼¬»:/3±©:ö×N½Ãª5_§§ Œ@eöYs¹èÔ-A¦³­‹Y3¯W˜ë߆^TÓ@õïÊÂmƒ6hîü}n7›OžNÏ.êÕóε)%´PÙKÒtw"Øú7ô–œìŽ+$Z8ÞÙð  ¥8ÈPòûnù×uå®2ÖÃÈl¼Naç©ÇÌî2öðíÛÙ!y_œ)óÐÃÈÁ“5ßrðÜÆáÚ¨MHEŽõÚ`Ã똽bo^‡ñåî_ÕÓÅ¢i%¹ýúD,—Eùß2ÝáP1.?´]û×ÓÅ©¬Ëy½¢„¥‘%,,a[8ý›b.â8ââËúÈ;)ã\Ð9nÔÎÿQH endstream endobj 598 0 obj << /Length 2758 /Filter /FlateDecode >> stream xÚíZ_ã6ï§æÉÌh­?¶l (°‡Û=ìá€+Ðy(Ðíƒ'Q·Ž³Îl?ý‘"mËž$3»ôéžlÑE‘ù#“xµ[Å«|/ž{øîÝG¯r‘§*]=lWV­R«…´0Ú¬~‰þ¸MMTT宾ýõáŸãÂw³`‘6ÂÈ>ø%Ÿã$nŽ}ÙÔEïòö>F?Þª,jº®|¬PT ¬“XŸ\G3ŠÖáï>ª<à-¹¶#ó¾9Ò¤p™ î¾qÛâTõÄvÛ´ÌŸ¶=”uy,vŽˆÍãí}’D¿¹õí½Œú[‰ äÝ9AŒ™–Ã>·‰Œš¾o/åÑ^“·HKW÷ÚÄ"Ïìê^J‘'¬øªÉ@e®º½×Z“ ) Ú_’0E–ŠX£€®î]ûR@• =ÊwGõæ O•“Î]t®*kwöØil‡¹bá037»—V gðD•Ð’ý«Ž–€/˜sކ‡È³¨†ŠË’¨©«/ä†8š»!RB7Äñ7Ì”ÈÒqëÊmû3~¨…Éͤ×3&V¾Ü–»ý.*Ê„Æs]0N*RiÞlp93Í‚W&¬Ö¯/ âÏ)Y_ýžI>è¸jžG{˜Cš± =òp¶öƨp½âÁ‰‘6ÑìgÁH%š–HÍv6GG­ÛºÖÕë` ص¬Ñ¼=My*ûý0¹£ pyh~ß,øõî™?=ÒîÈèùº+#òØÎ]¸ëoµŠ¾TLH™]ðb£d¢b8°‰Mô“«à šñ/²•÷ʭμ­R)â4])E½iQ­Y ™&=xƒ%"øtiø\z@þ™äø QN*ƒ“ßP¨büÆ·‘ˆ§ÎmˆLAHðr(ú¾¬wôÁ›Ä3“°BØý1läÞOgŽtÀO°ÿ½ÊÓi?ôè¾ø9ô©©Ê5‘ëâÀó6îs,MÂáüžÉ¸Žf½Q=µÃT±wýÜ€µöᇾ¨álŠvse1Ìpøâz¢ûw´¦ß»ÅbºHñ‰ŒÑ'=7K~…´=à:Ú!Žà~ßñ¥H…ÌÓÅpEí¯jt{ªª/ #ŽÅNNÐBTŠf²KÑž©Ž6à¢åÁûhÝa–èºø¤iݺ9Á368Vp4.}ût £§½«iN{ªY®ôlÜR`Ì¡’ôÕ¸e)néeÜ2·Ìù¸ÅäŸ1¯ÚxÈ X?Ü=¯Ý‘3ÐÁò”,m˜ AÕ©SáS¹6/“.Ītô4 x^ë’¡J󅽯¿{|)žöMǹŽvóÔáÊ`ðxæ+@Uäf‘k9DåѺáà@ލèÞ `*áåi30QË÷—8ƒþÀ(˜xÜánÐaΧ ƒ‚•ÛÉq.¡ÅV$¿=¡™7&4”eÛ"ܱÿÇ@ |„uQ)H8yT±ÂbOégøHâ­¯’\(p™yÎ]‘š7Öþ‡õ^|sÎð:±MŠÑ|ÿØ<ŸE—rB—\O0$óP›ƒÏ©ãd&àu(ÖmÃnŒÀ£¹bZüÝ#óáCæh’z PH­#ÜyÎÈ´ÐJ£ D–s¼{/´HÀÊ2‰ý%y©RÚŒJøþXôûÎp‡ÒDÅráþŠzµ©H æ+(U³|0)~çìÚÍR–ÏAXîú¶ù§»Wª£L]Él ­‡A[Ä‘?¬›ªi˜Äc€:0Àv ­-z·0D·/¦èïVÅE¬ ø2Þ°(0ÿ•¤Ïœ%}ô `Y+Ò +åµÂÜ1¬óŠFÀ›1`œÓŠ´2žzЊ¹ å5•ðéf*ÙÝþZùaEvYÊfÑÈŠPEÂ;g CÐð•4L´Í AyXNÝDBˆáUÌÎéž· b)ó"žyôãß?JFAPŸç‹Â ;ù8‚É®w62¹c¿h¢É_‰ßÐØW%ä~ß:Gôcùì*^ßÔhÚŠÒÚ1Ž®™ØõEKÅ ~a|È3¨©õÀpàë¡w®ÉÉ`ME‰G';þG— ÜÍW„ÞÙÀD'}¯ÆVlÚÕòT=ÄÆ t­G£ÝdWî›2)Ãx!áðÍ£t„`ƒÿ™ó¥©©6¹œá¢ÍPÍgÒ Ö !ºuÎü óG¯W*‡%O*zóIýâZÆZOýjy5¨t?v™æ4¨¾ÞëâxÍ€ âìZÜË‚Œ7kRYHûcaÿ(ìLÅ™þ«¶"MF Û9®æqjÜðE‚¿…@(j€iç|¬Mc޵Ù9±1 `lw:øŠkêðd¬Å|vòiÝ I±ÙÒVÛ¶9,“×ä6µëç×{_a,¾®¿asêê­±É5kÉø’µYÄfa-Ž.L5IþÒR’K\x’¥$ÇK|¢¥b‚¶v²lñ‰—òpj‹fM”’™&’CÏxvÔ)Ðă¥QÿrKÍE{ºÚ×Wꊽ°µøÉ(³Ÿ> stream xÚµXKÜÈ ¾ûW4æ¤fʪ‡JØpÀÁØ °@œƒF]=­¬ZêHj{&¿>d‘z¶º1°'ÕƒÅbññ‘T¸yÞ„›¿½ ß¿<¾{ÿ ÃM*R«ìæq·‰ÕÆÆZÈfÛÍ?ƒç&Û®ºÕ*ènÿõø÷áèû‡drÌX¡Ò6ü¡/aÖÇ®¨«¬„±¼½×* >ѧç¨bàèWŽY×¹¦¢IWÓ÷éö^%£É©u[ÙaûK(MYò‘=“¹Ò˜³¸½7FŸw|lI’ô—-QTu7åì¶wøÜͽ’B§rs/¥H#V pi•M‰/†WyƸ2¼ 'x‹²IP­ûÏÉ‘'÷#ëAζkN92ÓÁâÀ5YW7-xq%ã»ø®¢q¤©AhPÏLMí>;¡­uð­ða £1âµ àâúwdçv³jûÞ{žÖCˆé·Â Œ4ôiÁ”åŸÍ”MžO¬~»!¹jÂEÅ"IRzÅ'aÀÑ%ÀÅco.Mé­‘Tƒ½Š£k»×Ò}Xãm­C½°š–;û Ÿï%ˆITj"ô ŽÇç®)žNkg8í}â…UvpW€\KKs È%\)âå—Z×|e-ÄÖªÁë¶ŒÉâÕ+e@â÷^KØb®íÞ¹ŽV€6‡¬(Itp‡‹†M»yVÑ`’+Ô+zTnqrO^iEÆs¢boø*.ÑzÚö†ƒÂj»Z§íú8&¶;rpëhV ¤([>Zc­¸0Ä$N&á‡SoR¼ýËpÛ±ÀÔÛüê:2 °ã!éàx+ÂÊ2PGd'Ÿ/ ,×_0öúÔO ÍÍ´Ô‚Å4ì@žMZ>ÜÀšÍ54¡5Ôvàµ5zIN>ì©—ú%‰²ŽŽù®Åpa·ò z‡•#]2$€òáI4h´U•ãÐÝͪ´¹,pè)ËQ–ߟ›úÔ£ W”ˆ2—Tì6\0³go¨•ÚÍN{?!Õ=ÓâDSïÅåáJí™__(%°´z½ûC}´»¤ÏÜq;4b©XmAL"ŒÑ\EcE¤ÞRÆOC :»¢]ªK5ÑüÑpc,Œå‰ë£_»¦P€óĦ—$YÃVE+*åüST-”BkME(Ói½½Â]¥ÂÄk¥v»®wp„4‰Î+Qý½ç‡ì¸¦s u(/Ö¡©‘‰¸íÜÕßý‡UC,õåRíùØwb\šMb'ë+RáØð:þ+þ:j=„Ã!k™û í¬' ¬óTE^Scèî]5Œ·«¶âÇœ™Ê¼ÅT{é¦mÚì ¤ôå¾AAÂMÓYXü‘¿ ®ØjïENû£ }Ò¬€§H4"oQ] h%­Ð£óz}/Ü&Õ»ÑÊOBÀ´ñ™ÞkÝÀÖáŒ»«Õ¨¶V˜ÐÌ•ÿ„ÿ-÷\T×L „LÕuüLÂÆ¨žbø$J°f£D­4{Åy&‡XŸ=z¯ŠD¤ ®Kâþ4¬G›Éòo}¶ã aãMl<ü‘;–Y¾èÃ!…/ÿ¼ êÏså2]ñï–}_³XgÀòZ¢ù©äÁžT×­”ÆBJ576WÀLáðǬýÖ±¬ýÖÉ ÐâÚj¨WL3ß}‹u|?Ð1¢ŽÐ$Aí1ú]¤!izƒÖ3¢ŸßýÖõÑa endstream endobj 611 0 obj << /Length 1259 /Filter /FlateDecode >> stream xÚÅXK“£6¾Ï¯ðªb­„$U©­Ê&™Ô䔃o»9hŒl“`p@ÌÎì¯Oƒ$ÌË<µ‹ ¦éÇ×Om¼Ú¯ðê;l¿?lîÞÝS¼ŠQáj³[‰` Šˆ€»dõÑû1Äý5!{›ƒòÿÞüùî>½7B‚( A]+ÿs&_ŠZ¿7‚ÕŒ£0 œ ÊÔQå> ËGÏNòä¯ámUš{™'#c‰*ý¢ÐL¨xµ8Šbb¦.ÓÇZƒÛ ße %ðbÀhk¤ÁB_l¥ˆ‡‘Còæ¸TÿÕi©¸&ƵÍÁ†Ùøh~Ál8Œ¡‘µA4kkoàhQ¦û4¿îd‰…NfE“¶Ï~ÛLíl·E™»_'1t ¥^š_ŒÏ)jo‹2Is©>/•VÇWhb1ؤÃß>I­ÛóSý›ž®xå‰cÞ÷®8é´Èe6ã]â.‰·ƒ YgÚÁ[Ê})OÛ ÅöêÑ4‰>ç´yY¹ô¨gm$Ú¤?«êztÖÕAtÛ²¸]ùº]̼‡èØ ?<ù<ôdVÛ[HÄtØÂ]U;7FÖŠu2i5§£ó(|QÕT i'ò“¿f8öl=?§Yf®¶¥2õ ×rÆ\ôñø¼þPô> Åd>Áñ‰À„Ã’yòC潊P‰bôdŽ`:ÝÞ kóè`ôœ}…Ꙁ" .aU™Pˆ¸…BšÁ›×ÇGU^ä‘8€âä y„ƒS1<} "qüÁ¼úØ|ÚCVY½‘NÞ°›ü:¹z?òÝÞ@áw¦‡óiàbH®¥¤ M>VEVëŽAùå—K¤âƤ(Ú»Msâ®±=iã覓 Œ•“LæÚ—cлô¯ €Fsí+†íA*“Äœá™,‹Úüc ÚLj8çÞ?j«íK;SÂU„ð¶-#O5LP-]7D¶t„-ŽF{gl¼@­.=LÔ¥Qarèö·¤=¥ãáñ\ž»ß䮜;@áy†·ËùtñÁPm½eF LÆŽŠÊt˜Ó"—kÑs+Ød{rÿç̰Gç"z,´.Ž3Ü¥u4[Ã$ž¥3ëL|éÃåmdùâmß¶Í$jç¶{hj¥µ-7æj¶™ÇÚ®ûma‡¦°‡Ãê@ EŒ1cœ²Ðï›»ÿȾå endstream endobj 618 0 obj << /Length 1956 /Filter /FlateDecode >> stream xÚÍX[¯ã4~ß_ÑÇT¢^_b'AiA,‚ö¼±<ä´>Û@NR’”=ý÷Ìxì4iÝœâ¥u|™ñÌ|s3_}ZñÕ÷o¸ÿÿæáÍÛ÷Н ViVO«L®L¦˜Èàk·ú%y·V2†®z<¶_ÿúðãx~6NJ¿u[fëoßçÂR2ÎsXp{?rÍÛÃPµMYÃX¬7J©äCùlq”&eO3Om‡4ß¾—Ù„–àœé4ÐúêPû¯iÛ”£JYÆeØekûl›µÌ“¡g÷œi`#tƤö²i:ý[[5KÂ)–éÿ^8õO„+Àb.ÝG.Һ]QVäÿIÆ+Ñ2ÉÒ D“šåEÀ/K™àëš'{¹ŒÉÏΗiå¶N_GXh„//„þq}w`˜ÁGƒœ©‚NÄùKŠ@Õ³h£`¹Ži-M²³hÅÆ¢Þ¥NJú;¬7°¥íûê±¶4E Ö2KN4ñçZ›¤¬–¡e˺oiñ÷¦E&ŸO¶§Meø®ûr3R@$°õ&Meò®®¯ùP«áà^5Ä í8Rè >ÇÞî@UCÿ%-ìà^@j MŽk‘<ãà¬ØøŒãc?ÐþG·Ýƒ2èè‚ô°÷ëpΞœ¦`¾ß[;Ä Æ/0vGŒôr6è >&X&Ò©uöcÕÙù˜4¸ÁŸNúÓ3ê”äkëjK«Èà œ+’¡¥©G‡K¤X$€ÒãÌ¥( ¦sq*aàw•A D¹}"Ne„>„¡lŒÍƒ}‰¸UmÎ~#‚i5^ÃÈkd&~³(Už³"MçæûsmRr•rÈÅ‚ uš¼kè¿|ìÛšô_GÄO nàð‰ƒàJ€Ñu®´³)‚}ÝügÄ„µž<ÇPï95hv­s}TäJÄWOø:³Á?x²H8«çC]¶W€þ¥ÿûr¸p¦y„Bwó¾ýt¬p}¢/é£t™²‚g‘x.þN<ÿÔ•»Ê6C4 &ä½€$Š;zšü¯I¦š s#¢O¢U? €*C;{½ìÛ5QÍL*½ u4\ÒͯåÈ?FÇyÓoü¡Yeø/£&œ‡½OO.îåô÷pº¡ÊÃ篡¥ñúðÃçU>{ÅCŸ¨´»ÌÇ‹HèCQ}êTcî¨z¢ è)¹.Ç,ÁÄEÈÐÚ§^+Y2‚̘X0àìçõ¬”PéUÖ.»h*ûÊ|ÄQùR•u$Là4£Ü®bI‰©sÖ@ÃÄ(;•»–5&UÎŒs•A6²Äÿ`s¬¹Y __<5•ñÀ‰霦À‹˜×²]~n¡ 0»&¢@ôÙÅ(wM æZ,–ž`Pë!Ôj€‹š]µ-]0…J>ï-ëèœ'0 <.@áRÕÓ?éËÕ°ÏûÜÉ¡ÅeOÅåÁ¡Uzž=¼3›]ÙA–yÅd>+ÌZOçï µ]¿ÜÁ¤z ä¼HÞcbÅÄ‹U7ì÷ }óéKR%9Ác¬¿:X$â,fP_¾ÞçŸñ7T5xj¬Ë‡FÍqï³­d™2Ôå篵ùæ\$ûh;—›,ºA´i“Ÿ¥O£H ‹)ú;|¨¬Òä§Æ½¤ô_ÎFþ«ÇG;;1¦ùPÀ`‹Ü÷Ót gÁpžõçŠÑVl!\Þ_àvöÂâýñàKÜnðv>¿‚Jžä¡Ð2L­ˆ–Ò³Mß=¼ù g2ª® endstream endobj 626 0 obj << /Length 2209 /Filter /FlateDecode >> stream xÚåYYã6~Ÿ_áGéæP"aNžÏý¬æp<£GkòÊ1OqšXÏ´7ÞÛ²}m3¤ÆAõIUô,»c•£œçyÔ™¢©·WÊ:ë !tÍ®¼‚d-^IÄʃ° N8B8u=õ>b'§„­Ú®]$’d®´ac{Ðlzr0Û÷Ñ"HYÅóHóIP Å2žÌ}}ºÅçú»–=Z†8CóëÑÐ%ÆhŒò]ÙúQ¯ „YÍ…‹!0>©ð+ÞÚ'G£5-)ÉÍÞ†NàÆ,µÐL°ª€(&ÞâÑ;ŠAZ€ÇCr4wwïmº»»! E<3 Ö®iÞd>æ…óT(Üj`ÓQÎ*…T3• å …ï°ÐYÀwNFëçÊP×åYÇ:™ÔݹÚü¼pã1/ë¡€î,Ô´‹<ÛEÒ.6w»hé¢PkîTêM@ «EÀÉÉâ™q°5†ñ¢©š6Ç3(G¾«gÖ÷Jf8kEi•p‰×NH‹k¦%Ik…×î9”Èø¾Šñ$EwÉÝ‹Xàâ¬)É ^9xt¥¯±êµ‡!:;>@é4Ä`‰êéI~@j/|ÄêgícWðEi!oÈØ#u¡ˆ¦fÑ<º²§žZX¹ø±u©«îÚ×> O`@ sôÑ7Z·.tؤ5¢;æÅÙ'åŒ/·düWðe›w‡®"8£3ˆiˆ3 #šEdAÎ@‹Ä:AîDÜq†¦ÜÙ$à‰1°Î6)š¶µEð™hš‡0[´å½ïÆ•­¤ú,à¶g¡±ÌV¸î”?BÅ­…^kz×û™ž<R´ð|ÙZ)„á8}¹Ž¦JdEÀPCås±Ru=Î ìw;šKé1ôMó–7ݬ¢r~i§|uÌ”/C.­¤ž'ïOƒ¦7û®ü-Hd &Yr_$O ŸÄÕD˜E©ÔBÙŒ406…†SøBY9u¥)ÜŒ-aæo¤\²ŠY–ÈÔ Ÿ$ÎV‚q%ýÇÌÙä$ˆx“E÷–éاq<‚¼aÇßOÆ'Ãÿr§hN-)•‚[YÓlŽ䬢wן 2ËXÌåòjaÈx¾²Á;§fø´µŒøíŽZÖÖ}kú"t© ŸYt‡Œl“ãÎ:sC‹Ä#%4°ƒrÅæÁXfŽ—å¸@hYNàÂCNxÁØSéoÇfg¼uŠÏ¿ÂëÉ=æôã,àÃÓ|X.bÃàÃ2äÃÞ+®ùp ¤K“רÐ|hª §c¦£ Ã7IN9p$R‹êÐ$^ú;"¦,œ"ËËÅ>1h;Ä uá›2Mý]'`D‡˜•.þë¡[TÈ]‘WÃW(ÑÚþî@•Õry®?Øó¶mž.Ù‹³T«ÏÊJÎ^ÓâN¶t#n+ˆP9ÑÅ¥]ù§¤©Î½Šâû¶Ü^rç˜ñ0`@@G<|ݘò‘NÔHÚ ýc`A‘×tõ†‹þ”WÕ3ÍŒ—SIâ ‹LÏÔn` `üo¼Ðs^Q·„¨ù…TAi¦8Mn@Á ÿq¡¨Ÿ†$(¶ëêyÎrÿ'בò÷…ƒx‡ÈŒ5”Ê> stream xÚYsÛ¼ñ=¿Â“‡†š±ÞÇc¾4î¸ÓÎd&n§Gú‰…š"U´£üúî2¿Œ_D`±X`ï](¸y¼ nþô.ïoï>ÞÅÁMé—Y”Ý<nòè&Ëc?ÌaVÝüÛûÜžNm³ÙÆEì)k;³¬î7ÿyøóH~¶!PˆdK£Nzðñ®˜‡~&°@È߃4èôÿÓé Æ!œÇÞ'ü$^9m¢ÂÛm¶ðÛÖfÏ«xÀ-_ŽŒrïÈSBz˳ުÎ2¥cEñ§ÖÖêŽ?¨ ´-?üüÀ+m'€O Øò¯þ 1n…KLʼ>o²ÄSõðKé~ž–o’N­U-Líú¶Åðìy“¦|MŽ {Ô¼Ó¢˜.g« µ¡ätLì}¼ƒ[…‰'YÄlñõ¶qä—‰èû·Í6 £Ô»Gyê]6qèµOŽ gÏ›8¢“2ôºâÑ=Ü`‚güeà —Ö|ƒ¹tÀÒ¢Ð/¢O¾ŸXÈr/ÇOᙞ§MkyðŒ¢» Ï*ó=cÝé…`yÏ¡kO¼¼$™É2Iæ,A€%†žêRÌ©M2Ï<ÞˆÜi& :Ù§änx¥afÜZ 5}4jÕÈI1?0£ñ7Û¤(¼‡ ÄÌ–a adÕ¬nb`Õp?œ&û°‘=_¾Â5¿ñ˜l¾_ÿxǃ¬‘@Qi4š -"¬8L,Àd1ð톆—XOiôË„BáwÍö¾‡qb„ýÃvjoßãñQ"¡¹ ÐEkô•ÄÌx æóú¿þ…!½ÑŸxlšÞT‚ ˜ÑªŒÌêÄ^¡ó÷A>”;ãÞùÆ—B”HN ˜Ls}ÖŒ¦79»ã'^Ž r÷¥¼f£yHÊ“:¾vgGeàÂ}8c gŽ-–7¤¨Ðû\s£øDž‰HVÝM ŽÐ K½~œ:EØ¡kYu›ˆÛÜðfrUà³à-'¦}Íÿ ÀEà†«E|àb@JáË1" k2‚´»0Ú_öµ Ûc×Ç+'n«ùS"¬ãËÌaèy,ÈçPŽ€ùÙ@Nå9yÜÁKþ{© V/Hñõ‹¼ŒÚbÆ0úvªpªx}YÈ|ê¶p™c ǙžÆA´ö{ªhG+0>7ÄÀއ?û[Ll˜öõÀ%*Ÿ¥y+>J®)ÓV^Œê<¾€ÃÜ]‰‰«JQ ð['BL-eÝ´ ;¤ÿtAcE 2*šŠuÀˆúX;þ5'¿ ~´Ë ŽbÐÔ †šº˜uíIÑÄ=TK˜…2ì§öC²4±ë l¥©KÖã# {¶ÁH”R½ÍE‹ÕÙ(Ú^þ]pö(º8vLÊpÕàsjMélì.´}C‰wß<±Pªã­W¢uûE]WreÎB*ù˜2ÅÃ`zä†iF±PÔY·‘¨­tá»nèfÀaä?ºÒe UuÔ.¼ˆ]  ”",q™¢¢RìNv0/cÏÕÙÒxYlùÄN¾~^þIy¹Ÿ…ùÍ6ƧӒÉÅùéËûÿßv·µ endstream endobj 644 0 obj << /Length 2895 /Filter /FlateDecode >> stream xÚYK“ܶ¾ëWLéÄ©ÒÒ|?r³ɵ)ÅÞ*olWÅ9`‡˜D’!H­6qþ{ú8KÇ:h€@£Ÿ_ƒÑîqí¾{IûöþÕ7ÒhW‡u‘»ûã®LvE™†q £f÷÷ànŸ&zÔû›´JƒiT5Óþ&Lß1MÿÅ©>L6Üÿãþ/ß|¨¼Ýâ$ ‹´†³h³û“¶¸Sš]¿OÊàIZ7Ü›zl³àaÓš ‘unédíIæí´Oªà¹Õö¤õ$l¬nuã¹Iò°ªån·|Ÿzê‡îqS¤Q0ê¡U<©HjটyÆÈâQw·îZVa^$Þ]÷7yVÃØ?ŽêŒƒ2ø5N3Ü øåc_ó¢'¼²¼èÂN=Ð帯xA§ŸxŒâ‚Ù¾Evà–ÂÂM‡už3#þ‘Ìü84Ë‹àéd¨… Ó88 ZUÇ^‰ý„ä„_ó¨á3óYwÈÚd™Ž¼`{÷ýwÜéåóÂeB<öãYŽnÊ,b!µUÓäN3²ßç=Ÿ ¼ìc;sÐt×H.)ª<âal‡vn ꇖ/Õ {ÐiÅlШçQÛµY=¡Hô0}»eQÑÚ”ÞÍvêÏæßj¿Ø0Ž*‹Ø7 Z‘ÔÞ’$ “"skîÆ}ú¨¹íÔ«eÐÕöHxÜ8)órñ¸ÚTƒÖŒUÃÀ^¥Fr% ŠͨÛç=ørˆR.=…ã¢04 ÷,¦ÞÅKapÀÞlŒUfyº6FgÌ([Òmc@#“è+ }'j!IòB¤´NMO£[éx¹ÓÙÇY}…’þªÆOÈkôÀy‘ÿü°UÖaT¤N†üYRôYžógLQrãº1 ¬9(#ê?ŸqæA•¾Ëý†‹ð´ÏZ”Œ jé²"©éé7ˆ~£Ì»ðÀ»¦YIH«¬”pæ Õr¡‚.ÄEñ|îG²Ç}¯?“CŒp (Á¾ F|“º f‹Ž‹ß6&=!xñ¤jÑó8Ô[^õŒ‹ú™ç)~q¶š;°íY8±¼„Dã‹M⨠6²àÉL§åËU`»ª¦qyƒU ;ýärˆšØ”¾Ì¶§§Õ 5¬q±D–)…œ“V¿*p´fÈü³¼„p3¶ \©ˆsg·È2ŠÆr»Ø^ZCº!Ÿì­5èjθd!nËÙ8³¹·¬çæqì绞½„˜ áW«žL+Ö'|¯4"á㢑ô¨ÈL:­i´S’ç§hŽ&µ0¢GÆ¿BÒ÷{°Ä/8mwxÆá¶ï—ÕEÔ—HXDž a`ç'û£’&àÌ?ˆœšpV™¸ç‰Q¾T]Ã3)âjÈ;O2·‘OŽZM½7G®W‚vBëz1q…ÜÞÃŽÊ´êÁåÁ¹k]\±.Š{ð8 .¿Â_êkÑו"î åBGÈ@A~Óàã0òp#æ&„:Ú'8:8DèoŽˆ7‡@‘Õ’ÒJ÷Ù‚>q Š,E‘HÀÖÞˆòÈ Ïø5Æ b tÈ‚Ñ<Øôù+<¶ÊZÌ €á 6ZØ4!ï³$YA²ÇÕ¡#sK(lf¥„Mè¨ñÁ6eïËeq´¶6ü^ÉÖÄ–>Ìm«§×rx'¥ô”’‚8­˜Icº©¼rN¹ ãg3öÝ‚71zZdaUWýŒ mÜÇ5³{µî6ëŽ%{» ²<ál̔ض}÷H–}{Z:9³`ÐÒLhœ¶ogÆ& °^–O´Í…',;®Rï;rXå˜ 0Z×´êŒp‹ý£²“s¿~~<ùRÊ~P/BäÜuúyÝúãÛ~î1ÇXó`™Ó£{~Ñ[®Y'aVN¼?Ÿ4a—бKIˆ™ „=±c5cù@ >ý„Ž™T•Ÿ×a†Rõ<@™ª?cxÂà8O²”·Wgé1]®ãH§ê/¬á¥ŽÑȆ:àR”5ì„|2½?rË5gÂ×D„”¥.$Ã,·XUÔu¨Z)si!Øë—؆#²X¬:°Š‰?­–ª…ç(!‚ Æ (½ÇºÀq½Q+­ÔæåÔAFw)¤ì¤ºƒäˆ…<»þ8¢NpNêð”£kT2¾v%‰ôÓ3 Yг°Î²µnAÆY_D’E‘È ÉT_B ¬ W8©˜Òª‘½8НMÀ‘œ `6üï!… všž·µ½û‹š“à¾ìªxíQUu­fªéV³­â-@KHظyâBõæ5ÉðíÛð³_^3‰±AæAµì'¬˜È[óÚáWè-G¡f™d$òRæ üSƒ…vI (* ™ÁICû²“bï‚àà#.½ÝwœA®áøb+¢”%ò\Hìª\ ªö0·Ç÷h)²ñ:˜x”BpX<Ì#·¿B.ÝR†²õ‡˜ˆÿ¯a¦Eîù* ÐX°¥:–G¦k´Èz*~â™+Ãt$wa ú@´Xø‘ȉ ‡ TÖÆ­Ró T‘–dF@‰šwT<}­P¼©ûwÍmò§Û÷?/v¢Š£àÛEŒ…C WÐòó_†’¢òhÅ¿ïðw2}Qn"¶Fž¦{B‚âæÚ’.$gI@2ÌCs†äq1Î+|ÏŒ2ïÒ,Óty˜£XÜþaêͽš )ÉAUýÀ=NF¹1t&oÉ6Ú"yy¼Å„\ùÏv pƒsR'‚O¹å< ëïþüaãY*ŽÊ0¾ ¹wôÕoû//Éâ°Ì–ÚiyÓÄS¬žøªçýc_¼'òü@â #Œ^ ú*«µÞðÂøà¹A”Ò³U$‘[Ëm£'=ž ¿&Gu’’lØ=jà"/n÷óÄ“tÚIŽ[V¯+ ¦‘›vr@˹m–¯F (ߪ–ÅD;‹—¨ ƒÑòC± W‹òAÚà§i:g›JðZ1Á¥b0–¿Yö‡’ãCJ%ŽüwÏR‚´!Plè-6«$–ǰž@iœÉzêVh[.¸”¯Š*¦Lòz…}J–øà{BWñúE6ACû¾;¨Áb"àwË<¸£Hl'Ûf˜ÜÇyôþîGŠäDà§æ-GÇ¥ ØKθþ ø8^EÁY+¼ ®à$Ë=ztÃy#“üœ=Å(öVö¾æç ÓhÞ¸+¾†r÷ÐKkj+£~E"e__ý2q’^Œj3ññû| §QcÃ#Ïb™€Ûcë=¾c)Ú`º§WZ&íleiê^ï® Î$Ïú^Tåä”­ÀS„i¾žˆó¦'¼&/Ø^EÈ–‚ÏÃaRÇWõ:›Ö¨QÐ;•†Ø3ÓFÚlD’Z@ñð_³fhØó …5\BÜ Ô¿”·ùݸ W åòöÀiV4ôÂê…PØF¸â?ßF-“£þ ï»ü tí•â(Ì @)éþÇiå¿/Õr³ú\œïzM­bÌDÇ“;»š¦Ñô*^ýê"YÉ[`Rgpdy…ᜠþ†ÁZ«æÍêÏ+cè' [øVÄðÉtTyû…Ë#ÊÚºvI„/Á%>òO ó”V«Eïï_ý|ƒðQ endstream endobj 659 0 obj << /Length 3572 /Filter /FlateDecode >> stream xÚ½Z[ã¶~ß_abcFE]äaÓdÛ-¶iÚ Ú›}àØòXYr$9ži¶ÿ½çF]:XÜ/‚Åï^W¾_Þ¾úìM˜,2•Åa¼¸Ý-ÒPE±^ĉQ:Êvñ~ùƒ6Ñ©Ínóàîó÷ÛÆíº?ß7î¸/6ÿZ}¸ýÃgoÒÑ$‘ŠR³XëLcyŽÛUj–õjmŒYÕ¦¹Á ƒ<&›u}‘FN4éºF¾'Þ¾”ýð«”sl“~›XDÍ9Ô6+Pž½70ÒݱÁž‹m'­õnƘaoÏÑò41M¬yË}­,™ëÿT,ÄØvsøuby Š»­ø›º’l\%ò9Ê^تÆÞ§É<M¾åû¼¸ß£»É לñÄÊ&½Ó¨37Z™´71EúµQ¶S5û}NR×â_4yCªçîp,¥QŽšéð[¦:þŒ:b5 ‚O¤™4±©É`òkð½CÍyârdù‹”çÂЦ>U$™¼YoÊšºAÂùhsÙœŽÀ±EÓ½‰Cid4ˆ¤Ä®¹?ò ùé·ûúTn¹,ÚÈ•ûâ'ì–Ïùß0€xhb/õ»•w¹—ßçgfJGýI"_Ïܵ¶©ïãªûr~¢(1}'¿˜zQH ãD%Ö¼Ô…„7ÄÇÑ/{’™Øþ.ï>…stľ£kV((µB®Á¯rÉ!ùÞУBŠ•sÄ6W›3QB wMîûÊ4誷®Ùrmô[î‹§D­¼å¢ºçê×ß~w]½8,¢’Zˆ_C&Õw,Œd«,1) P’]„*€øKã_Ï Ì¤ œÈÐé–Ö·ÊÂÁ]G²ø×=çìÉßóòÛš‚ù¦Wk b]¾• Ͻ&¨rð8yûß$-µPÛÓ‘ÝYÝt²[Ò³'î7ø:Wrs×ä®»daÇm6³|h$g›ª8ˆŸEB4ÅTb&|káŠÃácÎ xpT E¼‚.:Ë`ä:öÜêd{œ¹Ü®w®ÝÀ|¼€sRIÐÛ8 ÐþÿkUöv `˜ÜÕÊÚ%€â›çºaÀ«ƒ/1*Ö²iû|ÒTEà/Ö£Nƒ Q®bš,P™~&CÄe´Ó—hïð=ã$yYr%…‘ª@Í»ø–p^̧§ù„GK@åŒV‰NV«ùû€ÆVcó™ ‡º‘™Ý­SŸºžA.̘„Âý?0pql-o²Ðà*Xêàå´6S±÷ˆvmB#q džís{Ú«AÚ¦.ëSƒZZoûœ@Õ’Âk"Õ*4í¾ÙÝŸŠm®ºüñ¹`b«²Tû¾[‰¤}´`>$TB©¶+ŒÜwî®|bB Àì¼gà€ýDïÂ(ãÍDñDEŸ|aªBD4Ñpt ^–A½÷©J£ GAJ™d#¥„ Å“2X:XBÄZº»í¶EFõ8îòÙF#÷јwÒ=í¡ùXSv¸qS´°K‰ÉXä-B°Œƒëpv›‰®_2&Þ‡ãåÌ¥§GgìJ|pÂ6o7M!XL™ãj=샕cNp·¬¯a’^‡IŒ Õ¶7’!¢ËbCÊÆ=pèç ®8>°áná‰"Åq•d‚õgXÖp2õÆ5ÍÓÚÜŸ˜Þÿ±Pr¢1Ùì©|ÎÜFG2yÌ9^‹Â]ÐÂ,%×ßÁ§ŒqljUbz`úÇñë¶p_Ö3.LÕßåÁrÎà(`‰ØÝ0è!üÒ#ýèD½®·Å?sÖý> Ìd8l¬õ÷šß´®óœL‚ðåœíIdgqæ&R¶¿*Å#åDT8æëç£'–îDc hzc¦Äˆ˜W6 é½øëU/›nv[ØQ_Û#Ø~[~=*PâFÔœ`öÛt'WzÌÚ*#ÚçCXÿ£¢,œ* nœN 8oÀQ&{êjpÀa‰ÑIS?÷”X&Âeî¼îbíH zHšL&žœ Î úÄ%Dæ8p^ò` ^¦í!@‘^øÂ'y:Ú<žÙ©‰Re/aíØP9·&Тϼ…Ë-†^G¸‰æ«¡ÓŒ&éXLz‘*a’ ’¤§cØ.]ÙÖ¼„¦vœ^NÒ˜4ÚÓ/p›„*Í’´éÑË©‚¸Ösäs£˜d‰Ç!p6'ñ<—ÜLwj*JjˆoÆgŸ†¨Óç¨Úލ°æ>Ï»ëaæö"âÅ$Ižtt¯Dgã˜Êa"Ëúè*ãÆˆ›ÙÁp*ÖžAlÙæ;w*ÉÑ ¹Ú¦í¸U’%õƒ¬*™dqÂÈeM§%+ƒ2S ¢än&ÆôžÓ)’42zÉ8mNH;GLíÎi¢”2—m6GöFl F …2›`TNÃ*€¦üe³ãYûÙ^£¶÷[2Z²V3¡˜ðßC«õ——YhâHªz€—X¡‹D¨!øÎ¦!¶:è º6Ô¦“©O†=È'’KÀwH«a{ü°ÉyêÁÁ¸û”-¤– éQô¬_&Á·¹­ÕŒä†L"<Æm-â |Gƒ¶a¬±Û‚Âæ—ˆAèI°"ái)ÓÍÓv\}½Á‹…ÌúÀ¦¹L%%A¸œr{,' g6±;±ºŠíÇaj0ß~jDçJ±pÜJËòÛùY$eX_dnGfÃîš7À IhÇcÑGã]hCÐZÓGh$O.Ø&îÁj°VQ ½îµX›7AÂ8iôbŠ‹³8Vš\ Úî2]&$9 }b|Wqh/-1È„"åSÿÚòyJ ¼¸Ûf‰ †ë*Bàãv‡ÇrW?ΤGâº[ß½¨&O€ ¥¿¶á£!]>•P]w@^îÊ!£ ×Ô0œz¾¿Ó3Ê01ÅË+ÈôXJþ/LÆ÷*$nRØXÈ:ÉŽ¡JW8š…Üt”;…îYajyéšÄE%~×ü63eµ9U<À^¯—Œ_ñ걎•" 2òæøöˆµg¹…ç=;é-á/‘”iíßúd0«Ô³…ce“°†UŠr¹À  ü0èoT…cT+spætú¥+™$Rï±4Z«’nô¯ iäïû®lñIÒùLüÚf Yª¼¸@ D)¥¤)Â¥’F†ïáÉÏí¤ß׀ʶØVŸJCëßnq§¸É–Mj¾ä wf³ã]cÄn¢+é&„k&ý¯žnS°â!a*éZE€E” ´ìÂm N9³NÑCŒ€KA¦U [%d5˜’p#oÚ½›•!CKû¬Å J¥<‚ɳ!8þŽì«lŒ?G×+Ët#¯Ô-S9¾þ+Gi•Vf¹Èeò’‘Éc¦Íd‹K~¹=qŒMñ:½sD2?Z²ÊŠÛϽ!vSU犨À@l²7,nšâˆ›,¿½ ‚z/å(þœõ¦%²‡Q­lyx!6ÒÕÅpÊ‘Dwh'FÞ”#¹§)ÀHû#2uÅ¥×e—7@î Ðä€g%£#‹¢>Ei‚•»ëß"ႼÎ{DÊ( vM}`Óäì&ìtFÆ;\âôò::ùöÎ<®‚Vâž/_ˆäw2wçÌ”6™·ñº*Ÿf^)Áu wg~€Y_KËP ¶FâÈàQ ´sø‚ Êº¢ãÏÎÇ×ΌÝ傟‹ÉÙ˜d2‘Í Ê&ö¯ù1Ü`èþxäšÜoü“…‰'IRãßR e±>“ Dr!³K¯¶ÀçÕIN.xÅÚãÑxì¥ü¤ãP+#ùJ€=ä_ {“Wá¯o_ýø QV°ÐàßÑÅg:Yl¯Þ[ ƒ¾*“¥‹3u:À¥=PA‚.½\|÷êÏüÇ0.¬Ê’„}¾QA"" “é{Ìœ@·@óC¶ŸRmüß)$• ¨ôfü°jÙmâ…·©&O¬“…y›˜…VpÿŸ¼]¬¤)œ÷Ћß%"•h#*ÑñøYè‹ñ{ÏØð(ÑÊ›ž1£e,ZÅô¥PµÝÓCVé¸ÏAò"ûS+É}yTnùázEiaúAêBï‘d“7þ5“23Qr(N†×"ÚW¸²à÷µ¿Lÿ!ãF2‡™JAÄ4Òd—úöo'V endstream endobj 664 0 obj << /Length 2195 /Filter /FlateDecode >> stream xÚ­XYÜÆ~ׯ˜èÅ@Óf³›—Hì(pà\ÆI é;왡Å!»;püßSG7¯™] †ŸX}°ªºŽ¯ªÛß7þæÏ¯|ûýãÝ«¯ß%›T¤Qmî›8ØD±2†Q¾yï5Û]x¦Ýî´R^“Øîb­¼ÿlåÕÏﳊ‰þd,UT[éí·;é•P¹70ñÁ—ú8´¦ãa]Ùùû-È»¬&Y{}Í£ n©«S³°¸Άw]óº¢:Nò?ÞýåëwA<;µöµâL‡†cò®¹ivn×NJ‘†Ö@Y{dÉ JVJ{õᆄ0±¯€Ré¢Ú—CnŽmÖœŠ}w-/Q"J"÷‹À :…Ö‘Õ!äµwä °‡Ò¾gž²sSš78 Èf8k¥ñ€ÎG”âÏ¡­ÏL‘øÇ·ï˜@G•võ'86òDâ½æûšM‘Ùç:ó€Ž1mVN,‰))Ñ¡1ÆŸP‹Tëå÷õPæh]ô%¹fŒ`÷]Ù[úBG¸¤" ž5ú{´ÄïÔÇŸéó³õ\´-”Æ?Á D’0¯o!°ÁÞ7õùœU¨ZzeñŠTÝôE]u<×!J”ôж®0bT@ Û(€@*²ûÒt“ dRÁßì%©¬t!¿L>±RþÌ.ÀI&B¥Ìè;p!¨AíGf‰vÌ0°æÌæ*µ/`åOÌ+ØOÝÐð¸nûާ8¶€8ÔeY£Ï9FÔ\6 ¬lÌ%’ øÑ!’¼]x~åñSgîó]w2¦·vˆf»U(_:Õ»þ‚!®¥öà‡m§èyXeg³’ºÈÑD阣ÈóåQ5à^W«¬7öh]O¸TÚeV©ù›U¹p½2åÅZ¨5Ž °“ÔdÞ ÷:ñ²y ‚t“yâx²Oý¸ƒ¤¥ÈÈØÏŸVª0qÇýWÑŸÀJoý©@#ë0ÈëPJŽˆ#—‹²äíyÑ5e†J_Üÿ† *€ìÒk'4Çùº² Á:Òä˜e$¸bøˆS¡C¹„®Ïë¡ãìk]ц²ÎHPÁÊxÒ‚mPäÇ‹€úŽd§^–çÅxÒЕ$^ãjDgÏ¿/ž±M9®ˆ‚rÁé§d–F8ëЗ~®í–­•RW+Þc.!;Ì%(ÙI"Wœ³²«é˜þÒXC•›¶ëå ÝÆÉrÀ†Á;¥8.å¬mïÇžåÂ?{—Þ÷mÖ^¶€2â6DA‘K”\bÔCaß‚ê *HM•w†sÆš¤Á Êp„›`¡q¹†­È*Ž×°E¿€d®QÿÇŽÇ£sq€NÀï‡bóŸ0?qböÅßÉÞ8ržDú2"’`ë¶G äògµ[ødDÎ%Æ6m •ìü’—6ìëÂR`É0Œ¨\ÃðmÕs›ä‡3kj?š‚VuKé’õ·*BªD<áá©B OEY Ïa8½m¥KˆÐÐ6”Vm$®%ªXHh»‡-õ¬TwB F²!ï#-aêàŠí7hMíÝÒêyW¦]tw¦áhlލªµg°ÊÛ_Øž ˜…PØ?ø¡ÏÔîé\2õ?;Ñ`Ë5Ÿ0M7þ%™ú‰?¿µù{þÌŸྴ‚Þó¢qšûx£ù½¡1»×—d€ ¬b{ÿÞ´¬Øëã¸wÿ±Å˜F\,‚FÍ@‹®ØÂƒìΪ^o”v#ƒ+Ž +²i©`‚ãŠÜäX üxʦ0ÈÕJ%‘×SØ"“Ø;¦ëxªèù;â,gÃçœÛ˜«¹™Šø˜Èëd'ÌSoªÎ‚*ì¤.Õ2xýsŽÛîY³{nz~`‚ ^/õ„ê,¹·‹Áål£ÄeóWÝ­SßgY à­V|ºk@ÈÏîs ¿ÙÌAïsá’ž=}IŠì´Ð€_ϧȔܽKyðE‘{…×H¤R5^ظù zFŽNE2^ðúú¸t¯¾É’ð-?Ü`«á¬oÊI¸*.šä§*qUÐ_êÃ-^|®Ó¶q1k´ÍSþ ÍãØLÍTþFjÏËŒÎYûih˜¦Æ/_Ür7â/Ÿ¸» %—/bm…¤§ˆ‡á‘ŠV²lšUÕv÷ýð0À+™•eu­íÿV…l.b‘Rö`Ö·£é3[G¨e Q6…:{ 8gŸ¶®Êà]ªµ”»)Óàײ†N¯"äǶ8UVþæEGÎÜéJ€æ79µ3Ï{3‚:-Ã)–CŸ èÕ¦¼P!âÊ‹ÈO–nÿ{E—šÀ6þH P:qÎcß1IycËÌ‘0›¼ýÁú¨ûùŽÉAÄ“¬uÚZ„%F\b`2sŒ®Ô‰Àw7œÍ:&¬ãì¥Ë¢}Cªi“{¤q.eFUTKÛMÒËMçÞuÆû´É7Âw'·Ê_¹D¶ª˜ê0¾íÔ¼‡‚‹Í³'È—›åàà€¾+¡l~æ‚y3˜Ø-×ýéòþïO;ÆÌgâM.-_oaÒÕÒ+?˜®o‹}ïŠÖhÈöøò­½‘©»óÍ—¬+a®Í*zÕZ;Àz•°03ˆ½~ âDÄþ˜53Ì\5µ@ª±ö0$¿l{¥•u¸2¾Ëá•í c9ìÜ}&Ûw¡ð#}3‰—] ^]lCë?7ÂúXŠòÅk„ì/²oê‹pºÙýšö C¡¥ n{«ÚµCU¤<½`9G?Û‚†Š_×¾§ßèyÍØ\åÎ8 þý×ïíóµ·`Ž0ÖOYÇë¶“Ôž¡Û Ey¢m£©lá´¨38ÌçÅyÖwºWkÈb¸PéU™6]uOÖgвÚÌ»Ç[¤÷# EU«ƒO1^”–FÞÈ’:3ÈĽ¬j±çOw¯þOÐRƒ endstream endobj 673 0 obj << /Length 2909 /Filter /FlateDecode >> stream xÚÍYëoÛÈÿž¿B8X w—ÏôS‹Äiwñ-îî%RÏ)ðÛEÿøÎìÌ.¹mäR ( ˜ûÞ™Ù™ß<¬îVÁêëàìû×ÛWo®e²Êü,–ñêv¿Jä*N”/è«_¼MÓîÚºíÖ¿Ý~o·½¹Ng[ÂØOezûv½‘ià5í$󯾤‘¼YËÔ{¢ÊÍã1oŠžzUCÛnÖ2ñÚ~èw]uâ£Úq8ƒ¿Þ„0w{¨Ì–ÞÞ´kÛÓ÷ ïlG¦ +iå©+OyW5wÈÖj#…Ÿ‰dµð˜ñ|½QQè‰êÑc{¤\E‘w×ÂÛÖÕ.ª¶¡±‡C‰·àºáÀÓ‹z˜ îO<”úsßÓ¶ág»~ Dx7veOÝÜ{×åZý.¯KÚÝ6õÓ: =_ó0'qòS;h¶Í%2ÁKHh°õD´c»Ðoç•}óš×å»aÌëú‰æ¿à½eWíŸ.Ïã+ ÑÔ۵͆—æUÓÓÚ¦5“¤zWäÓ Õ錱7ïtÆïWJÁ{廲ïËÇBï¡4KÌbË0‹í‡ª®iå.×:Šƒ9}ΕÇÊ®3×Á7´µ¨úSMÏ¡eS'Â?3ÇÀ62ô³•-õe–Y+ûWuzÁÆTì«XÍm éÐ6¦9h Ò=sÙ]™{šª˜Ý›w×,ƒîy!o®U0'›)ØÈÈÛÈÇl“ ™²)Êîíz§ ß| ƒ_ÖzfÀÇÛ„qæÁÂk©Óg[ ÇΓ@“…cŸÿŽ?ðºn Zæ²aæ«LaÜ¢ê…AŠJ¦q¤ 2›íˆ…Ÿ&¡@БÒô$üòŠ˜f=2oKÊLt ŸC—'xw~W–¨èé¨j h¤Rɶ BÒ––Àq"Gl”úž—¶ôÍiƒé'Mñ…÷Ój&sÞª_ÆÌùVcEŠ—»VI„“Ó¡ÚõîÙð @ˤÃw£Lj[ý´w 26‚;2¤€9•™§ñ‹˜¬šc2$àHÓÒ ©£Þ1ïîÇÓv„×·tÞ1¿_óèõ&p±zìÜë·*OÎTG½¶«îª&¯}4Ux½Py׈-ÏQCÞìÊ«‰‘ðÙ·uÝâ¹ZÁÑxÀ‘Sôe4PWMéØô3 ?Œœû1¨)+)[]FÞæ„·P UM7€ˆÛz$dÃÔ@L(›A{'ÿTì§QåŸT]½ß8¤¨ýï­(‚4^·~ÖqatœS› ³oÙG£æd§Ž âÈÂÌÞùô¦‰&©YOú.Èd6|ÆLoÃsiáj--œ8UeÝsD)?‰ûæÌãgÕ_BË`'ËÇ¡ú/ò¸SBxÿøñjxS{ßµÜúˆš…§-O!ÏaJë-|ßß|¦zк¼– „/ÒÈHË<%C sG{ja¼z ©#tã3¹X’™dBF :¡¡é„/Ñ ¦“k›Á>Ÿt­§¹j ) MðÍçÛ1T±÷q µìÔaúA}wO½’POÀà¿3 …Þ.oÈ¡â6îÁS!VøÒ8V.©<èÑtEž·g/=C&Œ5ØÛÃD'¡Ö_ôÉõÔÅE¹ïlœ8n\» 5abÆ ôöyUs,@‡º1²rÜ2‡Dui›þ×ÀVà –U%„™ªÙW5#Õ/ôðbûíRC?îÏ óP;ª¢,®ŒôJºX…°‡ù¿mHN•à‰#½‹¬)@± à¤}¿ >ëï\é °à`Nnèž×|Ã6ÊåÀx<×-JŒ˜²ààG£°t<|ækºjJ^¦5 ¶qT›z?Œ95ê¼¹)ÒÁ DÚ˜ǶbÍ»5ª"@ƒ…ÆÜe^»QÄÞïª÷øÚ<ÊH!ûÌ~¾_ù0ˆo7ÒÛ`uŠLû¡ì¾3.ó\@xä8´`!Õnò}ø®º8c®ZðÓ“—6ÇkRgMQu:©Êž‰ùÄ»~n*Ð¥Gæwòœäž© ÷Ž]öÌa„¡ãñf~_o‰"=œ[°RÒOãØ(ÌŸGHÕS›þíÓïßøœ=¾yV ÓÐR›RErDˆTÏã¦Ûâ÷.*¨ª­ Quzï&L¤é<$™å!LÙÛ³r‚Ÿ‡xää¼h1—¶lõaÔÐZEu)ƒ8ð³ÄJöÊ  ¼¤D\Ÿ)ó®®L0ýôÁ"~ê‹?¿Dü&ãU¦K(ßÂ`ߦž–bäPú2Êœ„‚À’½)°h‡žøP–ƒ­¹oikx/3ÁµRº5¡o}ÍÙ‚^ eÒeM(o$rq' 0šœ3ÙÓ ¶náp)”S©ÔÝ(0 …Y¦hp ÔÓzn<¿^ª}óÅé\+Ñ.È1P4Õ7Ìžc`S\hø³Ã)¿b21ÈÞm?6Zm!ï¼fêwsöùËÝÐVì¦0ª‹ÍÔoM ,JfÅ-èLR»teIÆ9%.•¸ÆÇªF„Ì»'y¾è%å§¡ÕžIŒ8‡9Ë Á[%Ë/Êøñr|ÒL3rû@[ï¥ôPJ?H³³ìU-‰ç¯ ½©¦”„”¾Á MÁ }€Ð®fŸŸë¬§²ñ$k]’h­;N¡¤»8qÇ\L‡_aÅx"w ï¥! ƶ³Ã,õ Å ¾Õh4(jÃÞväâjÅß]xíî{”r¬ÁcÅ ˜6éUAûÂð,ÿ~ùiKû´&0œ‚J¬±:¶ëæÕ8LgÇn·à¢Ðƒ‡¡÷Ïuª8ËU&Ë ÑvµO®Û¼p¥Ðã/0`‹øÃ…ò- P1#p,í¦Ø;–†)Ϲ¥© önÐÐÚ^§Ð#6…†À̻녬H(?œ~ϲ|É8&¾tõÌ»m 0š&votp2û Æô8‡Ul˜ŒŽ‡¢«×­H#¸ü鬉{eJ§÷$ <”GÚ\Õ€…`ŸÊž·¦FK°B˜"_™)?Ž[ ÓNgÿ²ò© Çž­¤#h¿XTä.’t…–€E ?PòÌìWS Sb*()9—ôH¥£Ñ«Z›©Š†šʺ¤S!‘3ålBòì}¯ì¶„Í@„1»|¥°áµ]?PçB™4ü¥Bs¹=äŠ3ï/»®Ý¢ ƒÀ{Zյޝ`®í–°D$~¤l˜vê%?è‚QÄ ÛB+—ÎcСO \1qù;a( kúá ¾"Ò_²lªQÀ ! n­~#Ù¦FcN£ò"n˜B¦s!J»Bˆ¾­ÅFFc^S ¾Ÿì]ú5Æy Î…anþ #ŽªÚ±.hÖúªŒ~æ¦4:³W2úm·æFR]hXÕÍH›R +ï&Bîϳ¸­héËB2B¸dRû¦Òüâi"í2þ;™RëHeíV~ûaª ·´+üáé¾Ö}Œ„Rþßø0[tÚŽUíøµÐñküƒ¼àW"Š ¿€ô™Ÿ‚=ivBá,zûê?hø­ï endstream endobj 684 0 obj << /Length 2729 /Filter /FlateDecode >> stream xÚ­YKsÛF¾ëWðV™ãÁ`ðÊͶ¤D[Š­]ÓUNes PÂ$Þï‡x91y±'tFŠœP×ÌJ9Àˆ,CGÒ]$P4Õýè½b¨1º®hv#*Þá»J¼Sr¶]»nÊ}GkÂή”õ ºÓœi²lÆñ sl΀»ÉÜ=§Ž"/»I C=Pµé•ô4]7-Ô@ß,Тï. ¤ '%šN¸Dƒ—hšì‹+$* F%Ìl‰ÖÙnd¨ˆaŸ G…l.·V}Yñ°dþ¶h#ˆ?§t µÐÊÿ^X€ÄÀU±®2Å;;Ðd›1NÂwÈw°ÿBãwUñœQ¼àô½±Æ¿ç!üí›Ç¢±ÂF3b¥=x‚Š·b|-ø’¯BïzC@¿²©wÛÂŒÑqwa&+±®=SF¢k%¨ÐQrÆ;`8ºi2Ð%ÏPP0º®‘³ë+‰+:::Ùô.„'§m\AäDr‡Å^w“6’&àX]Ut-.»PÜ;[ 9ô‘³ÕÈ×õíÇ彯 ›¤XßÃåø1›ïáæþÝ<¼åÍ×ë»0Ö !:•]øæeJÔ çÍÃP‹L{­¦ß±Ë=äà±!xø³¸(/3\˜[Œœ¸·ø˜ðéãòçw—¤…I’©´ZºÄ‡3‘ò‰Ö)Ôå@hÑ·Ù½zÞ¼@Ì\ÑÅÕWË :HýTàR¸ã#ÂÜ÷˜9Tÿf¿í²Ý‚rb˜Š09ΉYcýoòÂuSì\uŸoÎ<‚H¡G2‚÷KFù!=tF¿¾yÿåÇ æŽ"‘Ƒڢ›¶Ý¾«ÙiŠUÿøÈÞm² ØfßwߘËöîㇻ›Ë‡ë[ðá 2úCÁP>B>•íi0Mp5ùC)ê™ÆÜf`nb×®+ŽP{r]ï -©D܃;I9“Q|0¶ ¶ü™E[Œ:جbŒÊ!¯‚vþ ›ZGÖ¾¹¾[~º¡‰t%hñŒ…ˆ d¬›q¯0êu6v©†¢N`ËBÏ¢ÿ °æÌ"ÃÆçå/÷7Ÿ/¹pˆî›¦T{äxq—j‡weÑšÎwHØ9¬l‘â̶\×øÓZ¸H'OQp|E…vý{K»ÜÃ}SWbŠPhZ‹¢³g!‰ñ*ˆ0LŽòûqe/P„›Ó4Ôàßpw ´˜å 28—I£PD±²ÖY™Wº¶\‹²}9ÿð’:ð…Ú(¡ÚˆêIdhÐå84Ø”à­Ü,¯þ¸B‘3Ä)ô2z¦ æ5vëíÕ¯¿ÉY›P[BòOfCº)‘&èqÕìóÕßé±z"K BORalK¦Pflp¶ª ©zÌÝíªZl¹ÓQ'˜J¡uTךØM¡¼i»b»8”ô®‘œ¹7Zò¥©îfŽ í1ÁqGH+´cëTäX`ƒ¤ýÐ mÚ&ë+Þ‡ºï埑û¦¯=pLćÚòØ#`MNECoÀûªoÏùK Q˜º„ð×[Á5ÒÛ¶{9[Õ…‰\¦ÞÇ/»òù2£H‹$ >÷办›—·wÌòó+,Shôˆ%½ñ%©ˆã£–ýÓgB¡¯—¡GdÊøzîo–XbQõÓ ŠS¡0(Rƒ"j¾ƒÈ?  J'„ƒ`<Á ¤å§r,òÍkÒ#Ñ•ŒGPa R Èí þ£Ãä3 |%dÓÈ(柳ˆ¡±ÿß#Ö—©Oñ¤NšD¬ÔCÄÊà4b%C'nØá/&Þ #]‰ô$*ÃÐD%ST"=¸Û¨ÄÚÑ•¸ÐšÄl"Sù.Ú±Çu‹Uóãb•ßXp•â1j. ßUŒònD5ÒA›æÒÈ+Qƒÿ§ŠƒøLxòà4`"_ªq"_RLV¯)$¨4)¼A¦¥®ÓƯzM(<"œ ‘J«¿±¾TÂÓ“šòîç—Û¡8‘t7é‚‚³!†¯kW)ºRØ5~Ãû|LÀ-yÑl²uqY–é®?}ø†.JÈ8¾¤ ½ 8E¦²æT»¬{[kf}®y]Tbyl÷û/ï¾*)¡ áNn\H¶EÖл¡+'ѧÿk»ïÍ¿øÙ‰<§â›æAjhŒÜAI« ÀáŠeòé endstream endobj 595 0 obj << /Type /ObjStm /N 100 /First 880 /Length 1440 /Filter /FlateDecode >> stream xÚ­XK7 ¾Ï¯Ð±½hDФ$` ¤)ÐA’CÛÅ’[,ØÅ>€ôß÷ãtÓÚc;rf÷`˜Ò|¢(>¾¡Fk )h+¨â¿¦˜S`iÁþkü…Ì>æ Yð/A1fÆ¿)ÆÓo`®ÁÄe V%pæPØÿ-óu%T¬eI¡Šk¨Õÿ)4àŒR $ aP.ET2fr É6©Ôgðˆfàœ}F!ÆŒè`ƒBÁsK BsÍ8ªŒ0cV‚á°TôÀB*=LªÏ`¯Ê>ƒ-ªa9ÔàÆ6Ô&S±W«þH'ƒf.ð¢ºæ Á-,_¹…“Óp®ðl&Ÿq÷øq2ál… ø‘ „§Ù]ÎîJhÎê6a/8¸P\» Õ•ºÐ|ñàM` g2œ-'Xç1ÊäË%­ƒIÐ<|¡Î.4‚¦3¹@Ô†€œ1Ø%» Š Ð¬ð1v† Í{Væ‚ ¢“«§¢“›ŸÔ(Hrãá5IžA–ƒPñG„᜹‡bèB–ÁÌ$°!L"~.k&…«g!Â$+)HK¬HZ]€æFŽž¦ŽÁî­é`8¶&8Û€ÓT\  DŽqÁÁÈe(³ªA3v¶jAÅK6©¸Q?*Õg8¨²ggÃør³¾ gga|™Ý³øØŸ¤„t/yDîâ/+^½¶ùÎݯÈÒøÛ¼¿ÆZàdÂÝ«ÎE&Ã~ùõ·7œf}÷éÓÅQŒÇ¦E¨íã4Gxrwđ۾ÛrÑÌwÿ{{¡ï,å¹ïœÇ–ùÎ˼ç»] ªÖØZíã EBáôpR)"i»0Ë1Yß<®H¶‹Ë-2¨®‹cì«ýã‚Âc¯uqZc]’RÛuÊΟí~ÂP•½d[š_DûùÕ–æ¥~~í`Ø.R®}œ$8Òº80jÌÖ×'Úb»öpx)ÅCi=ƒ¡‰\´K(êo‹~"¢•8)oŽpúâŒØckï>–fD9!#Ê,#pôÜÇáÛÁHÏp’#¢*{”£}u½åìá8 ˜$wq”5V²‡0ÄÒH³íEšei¤Ñþt#½ƒùJ¤g8E1².V”CÅ5áSNFÊ; N'Ç"åÌ{Éé¤À˜Ð<0™úÙÁ|%0s!wOЇ®4z·Üáώ~ìâÀ¢ÎS=+¡¶úûâSÓ.®qÎßž7ÛïïfñŠXd/W„—æŠä~®ì`¾’+sœz¦}\Bqrëâ¼áÔRû8ðu)}ûÈ;ÂL iß¶˜|ìò±9Y¤¨‡ÈÂædÁÑ¿§tq*Q½¨lÎÞ´õa Är,˜'^ø¶k6ûg§òhŸf¬ì^(´´KzÌrdĬ6ÿ‰›ŽÉ(ÿžêW­Zä`9ÞÜ}¸Áâ«Í:ÖHóŠ,'|þ(ŽpgQîâ2Þ2¢ÒÅ1§H¦]Ê(åof•Ý{æ6Åø÷ØÒöÛߥ‰X÷™¤.f’z“ÔÛ˜9ŽýûBëâÄpýãöÀñNãè0=ÁÉÿ8MÅ. endstream endobj 690 0 obj << /Length 4069 /Filter /FlateDecode >> stream xÚZÛrÛF}ÏWhób°b*¸ƒÌ›ÛŠËvYJìªÍnŒÈYƒKd¹öã·OwÊ”³U*a¦çÞÓ}ú2ôO6'þÉÙw¾~Ÿ_}÷ã«0= âÓ(NÓ«›“,»¼tkûA¼Z£ëÝ4ºÚnA»¹×erÝ\«½†ÎÖ°lst½ÃÁqÖ 8]'ÊEK«†ÉÚ Öëð)³åcòN*yMœäå°H)D:n/%²Í]K#_ÜŒQ’lþiÛ_ Ù¯mj]¤¹‘¯¡Ë#nmQ[Çÿ‰øåÓèZ'¼³½öx“ƒ}½ããg¡öZ¡=ØáÐ93aÆ{Þ^×wEk÷=‰®¹&†ïòž¶I7–d!_5"Töò•¡”Ë[¯´“Ì"eaÄtœ«ªL©ƒæ¢F;V™Þ¹k¬±ÍÞ\õnÐ{[ôÄ£c‡zÉÝÿ²mSC0”§ Õ?öî¶¶@ ¶ï'ÓÕ£Â[¥>"ÒDèäàTê­”b¯2›¼âÚÕg¡²¨7]A[è¢á“•Z%} ¼RËò§Šg÷‰Zê*×B½„µ§|`‰užúãÖ@ŸÒ€YœúÞ]Û@"@‘“ “´]/Ô™< âˆ^î2„šk÷ßúÖ œ²œÕ¶Ú޳õNK‰nk™Q7xݰÛ1xÌ–#MŒp?éʳ½ŠÖðUã°Ëc§í·ŒF‘?‰•G‘£ri[SôÕýby˜=r·Om¶ÞšÖŠ,EnwTü1JÅ ‰ÑœeT9TaPøÑÏxPâRÂS_ ¬;´ êñi@½©ÜÉüGÅú:ïxÃ1q®–ïˆT6Ÿ ZSŒDU ¥ÒŠ`FyŸ^Ù…/ÔçµÉëå{kZ`¦­LÿD'{ýþÅáø£óç—˳7RÁ|G÷"ooqÌÈ{§|ÜA˜rˆ+Îi}…Æw..¥ZÙë6o§{tû¥B;€Q, !ÂåÙ¹wÛÛ®g ë\7ÈCì=®E/ æ:@_¯<05óšýPÑ>™Ršmà©(ì¹Ð:é´É <Ãþ¯µlÌm'ílˆˆÌÒ‚Ó Ù2t#>ÜPÏÆ‚‘ dŽÕ²ÒAMoµÈ¬Òá*Skî  j<'±%_ƒ¥”¨Âi˜ÙZ2™üOò¹³uÙÈ¡¹ÞÝw½Ù©Õÿ V¥jRk¹0dÆ%žeâÒTmu%‚…ªR nzÙ‡úÞÍöé1ÕanF̉…ôiyˆƒj–ààÜ=@E€~gîݹApd,œ±ê·°¢¡XQj/mY?Q˜Û²6ÉúºA10€ÌF(²âÝüT˜ÛFØCõ‘Ó—¶ÛWù3%¡wmû]¾ï¤"Gw–‚äSã’’T`™ˆE›w[7Þ ¹– 2Îy×Ô +ƒ¸4mÃJúR¾LÑTlá© ¬ ã%mGqúζÜ}ãFEÑ3¹ªX…©MË6•*"Û¤ÿC½Ë­xôͯÚÓtô‰¡UIøÐq—q’DÄ8YE­öãÝgw­€vf5ˆo ÛŠŽÔ=‘¦wí&¯í†.éÃþš. «(ca™ ¡~0ËÇÕ»3yë #ñ3føÛ˜ã8þT¨ÌQÎå#:9TJ­rÕÕÉEBZ=§ οj¹‘!|jƒ0q2MÍ •3cÚ~ù:×>gÖ|Ì>éŽz­ožaá³—ï[¨0³¤k±ëÊ`YÌŽc×Sl@çŒ!Ør-Ø^¯$>:zÚºÛÛVÙ.|ãóeÚ ‰N%µÑäŠÈ—:áù“´³Ç ¨¸!> •NÖ;”XÇØOY¥còøž›–7ÆÔæÖÒÎN¢©k:SÇí‘÷z¨`ñÑú{e†©:ù»%g þÒÈ”Ì2ïCQXí ‡§¶gµ­dŠyC|LÉE»Èk•Xл~Xõ²²Õ¯#ÀSû@Úlö´}ç‹ a“:‘WiÝÉpæN:/˜ávò,©KgÚ¿F4Ã|Ì—Wûm¾Ä•kd°¼ßmí·§½èNÄ’„dUnàòèLǯgîÍE 81G'½Æ³¨Coœ×Ò÷•£RL¸,‡: í÷P»Ç‘ç\<ÐÍŠ’ËgO‘±b€U4^‹TC£PŸ6Ì­Jå;AáE¾¡ëÜVRû(úrÛm›½PÜ´?7»ý ëäÚù̦÷H@ F*ò(ò•M fQªb¸0%'HœÃ… Ýo5½{ùÊ hÜ3pàç ©\ÞïÜ ýµg:ÝDaÕ¤©î$n¦îw‹iƒÙ`+½Pdé˜ä÷vÖO.k-Šõµ¸œSU ]ߺP$Äûg!Z!¨úŠß ðrTzÕû¤ûø‰€:à­4NœUÕ2ïÙ~_ÙBVý^Ú€…—û–L‡ÑuIG³§ ‡ RÓDê:Ó­ÐX‘®‹ó\ùµU‡¡b£eÓ¶Ütéæ@/ð¸L‰¿oÈHKü%×é\ œm$áØ)S¿>#p©-D‰X–‘½; ¤Ñä×ÇiL~M[ ÷ ‰úÞBþ@œ*Õ`¨KÿMH?ÿðÃÁ°¶º>q’±@P\¨êb>ó nñßøôÛ굜Ç_ÍÎÃN/C¥r0Ràƒùê¢`È‘ŒÈrCnä; j7y­íÝà’•¨¹…®x/bÉu˾µÿ¹e7#ó>4×jýúå{öÙÙ"_ï9§‡Éþö g9ó³Ê|Î%ü ³PmV…Í#ݹRWM—ykM%å_òv)'AÒ4n¦ Ž‚ÆÙTRy“hÅ‘ù'è±R‚VÃ8}#ßk'+¨ pIéþBß¾›ìxv§A¤ºNxƒò0 šHbÀ©N_¢!Ì×AÎ ê˜áõ ¡Ñùœè³:·1ˆD ©¹c(oÊÿÎ4…]_ñ(P’‘ž*×£ ïfçœyó ¶gÉ2üÇý²i­ú ’ £:»©¥çÎRXrË7 5I(nÖ<)îÉeRäá€(Ì3Œc°Ï`¸‹¦.—Î(±&÷XlÊ*¾“¹Î¿e"ã~ʰ› å\>cü„V設o…”kœ=èì¹|ŠÊä:å˜Æ¯-´˜N¿Š ­ï¥ïtçÔ§nzŽÒ•O6Wr¬}ì˜Órt³ÈôHé†"~)©à8E{=H“ÅA¨~]$Þ`DàÑ›J%«–NÜËœ…”¯j:]˜9ñ|~!…+àGs{¿kŠ d"Ž’î¥¤ÜgáO|g»Ж†™¬¾gêž1¸Äy”fæ#Õ{K=éÀwšØŽT=×ÿå./º¨Ý[‘7w®ë×öAZ…T€äµX=$óêv$ÏuÍ2OZ~©H8‘® Œ†ëÊv¤$,ƒQ@¶”] ´™R] È…Ö#ÿG×ýTø8‰Úé-žï¾b.ijíìY}]ÈXµ°)!RUŸnhî‰Ë#G½ÑQ]4úäS:TxUp!™KH•.Ã3‚ЛÎ_ˆÆêíŽf:—E›KcËÃãêsé2®Œ_1ò‚Q5{çuÒ¢‡ýA‘`,H*¨Ó‹‹aæQ ^`¥$.4‹Jªª¹g'DF»X ¾p±\}þT†ßzuöcàÊì‰ejb(8KÈ,¿²ä@h²Ìûå? ‰ïsp‰Wœ,ü÷"&oÌ8Ҭ׉$AŸ.×{ ßµùÍÔÒQ(^èlT_‘¹æn¶ 7A®ËÜ7÷8®Vîç+ƒC4 ­ù:å:G+÷Bˆ›fž‚ï 8Ì(Ô†öÔ±ŒêÆ&¢ª>I<Ù§òø‚÷Vú½UñæÞ×C»Ác/>‰ø”7Çb|Ea¯ÄÝ ¹£^.G†UÌöyÛq°ìûÎZ­ùç4øòÞ€6¨H]™q Çÿói'JVt!ä²±rœéÈQˆ¥m^ô’z3îF¥½Î׉›rš«­mK÷²^iÒ®¥8ÆåG4ÏMT'}41Ï"ÍOè­n¤ñŠs„’£il¥Y1uX¿ ÅGN+aº^Q ˜4àðyuGظPÝjÖ[ßOÄý’ó\ §¯]¤<‚¥;)º ç áwBW‡/yñ»0óo†‘”6JŽcåS>êZ‘q¬u ckJõŠv‰ìm­ jv•ôgY49¥éóÄF{þøÎQD•Z¯É»1mÒWT]×ùoob§h…Hï‘hEF†ÛJª˜I±‚§#ð‚áÞÌ„­z{3´#®ÎßSÄÓ6¤æüR|ø.bµùn¼—Ñ孩”»g‘oü*cÜW¸Jœ©E?pLfqjã@¶HüË3|, Ón–3à)å³Ç·o–ôG8Wg‚_â…¾›¡DÂ,®ÝØÞm`– ¢Ú§‹78ÏøÏ“`ž¦Yt²ŒèdY&'‹£ƒN/¯¾û6ä\ endstream endobj 696 0 obj << /Length 3964 /Filter /FlateDecode >> stream xÚ…ZYsÜ6~ϯÐúÅT•¤Ãk&o>E‰Ø±oÕz0$f+’˜¤e¥öÇo_ࡌ¼OD7w£ûëã³ýY|výM,ß—·ß|ûÃúlsµ)VÅÙíî¬\ez•”@ÕgÿŠvÖµª?¿\åëèSœÇýA;Íäýùj)ÏDgñ[FÚ÷ÆvÌí¡í;ëH³T1ëÁMÍäA!ýù|U¹ÞrÍvj Cn)õ2heÛ[ ©T/mÌáŸoß\pÉîø[ÙÁy «I.Îÿ}ûlÄe’\mrYò½³ØGo¢OIš™y£Á÷KÛ<“Jاoº=3Z¬à²ÅEaaZ8RGå&ùÊRUMSa–ꤙyg÷NµLðnbÉ çÒ»úSœä°è/°È4Ii,‰DÀô~±ÈœùîõPŸ¦°ýýqè/˜Ð_z§ª›¦Yö"Ñ´Ô¥2Q(ìà¬aëE°V½ºx$Q9 ó“>óÆáaö'Ö®1”Œ ÷*iI1ÂfûÁé+Z[’]m²l¹ÀMs~™­2Ùµl•FN·Êtº¾åï¨[(RÛN3{ÔÓ÷Îô:t,û­S wв×n§*˜ße™Ñ[åî¸Q-_j·gyÚ§YYtû;­êòÔ²¾7]}°rO`Ú äé&Z…cÉàIl²ˆÕÎzoèº`ï/ÔµÂÀeÑWÝ‹Žå-×ÃŒL´°á©ôâl+Í´ª°Ý5ð™C•Ó^+ǵ°ÅjݤW<»N5§´²ÖÞìqIyqcÕíIu€A'BÖ)Y1”êÁñ Ìš…º²4™l½­ð|®MsžDÍ%–o~ùíæW~<_ƒ~»;°Gnje¯l 7C¡5ƒÙ’ð5Ý,Û^žš¼î\þ,‰ÉôdI"=b÷Ú©ãÁTž)RJy[ÁÄšçÂ}©›Fç¹î·Ù.rýMÖµHA€Š£pzëX¡Â):(<°Ì*ŽÓ T,±.È#K5HÇ'L éüÑ8ņ<+2Ý êAs®&a¨¾µþÈ.‚éGlñÃngÁâeñz’iÕ¾3¨$•ÑÁ¶ ¢%+`ïèÄQz+FË×÷ä;º‹SÇ#[ûœ´iƒêUÂⓈŽtÐÓî㋎`ç›.þlô=èEð;3ì@W1ŠxÚ)ä¢ÿ Ú4Ϙåt£•G#„ÒdÐóMÐÛMôZí}?¦+ç•óÄÚ«*˜Îk ט4í%* rßNꄤè{+Öæ·uäE‰-[„åÙÜR´sèyÝUb¬éÞÌ,õÓ¶ùWD ”hÑO§9o²‚KÀ2Ãòß$á„lA÷¼gø˜Kún«:Q¤…-ÃŒŸ 7tï%XÓ©½x bñt÷´¥ž!ž,Žrþ¶cargHWx/3¸ð4ßOñ*=ÏÊU¨þ|Ηö ˆ_­ïÝÐ2Õø^K§²p(ƒ¯×ÍŒFW¨7p¤x}P v /Â=ݧU:CX[…AkéïÞô@ §l†ç­ þÚ´þXhh°><‹Î²è¸Z4åÝ%ñƇK5Š–7ªçCÇê-Ú>C¨ ¨á(#óç¨özy–8Ü¥ ¦À‡®QžÖá4©p*'lPFh#<ƒ‹2øòb‰¤Nà1ˆŽ4´UÈDPy^"Ø|DµÒk1¶ÜÝA¢‚=â½¹Zÿl|9›=#NÁÌ#¤ŠR5Áïÿ´Jßod›8}²Gqž¬=²(ê~”âÝ’½g¯Ü¡«áôvVYs )i&ˆÁ¯ÛÃdÑlg%:SË#ˆ|Ë7ŽÊ-E_ÁÌ]MQÄŠ\B%aŠýMcÜxè•Ö „âÏG€¦|{=7þ,÷œPJp¯å"&*Ùøyýx°³Î9,Dr ÇAÃ8ì † %-c=€`è„:‹ÅÂ]5ÚýãÉý¸•§É|¦«™_Á:qéž)Z$|g‹ ðÁ·%íž Â¶¶\ WËxUwøgÒTP¥/ÝÞð§Ó²×,Ð×P.èëÉ»,[V¤Ô|ªæÂh Ýká+þøžð´Xa™ïb'P°Ì&Ô6È”);® %gÊæ83Yr®ÚA°gj¶í@õpKÃd:)hÃ`ËÛÁ4'ïƒXaÒ¯x¡~`1kã+åÀ*:.Î8ÁŒ µfبfJB!(½ïù»â„ñŸD)“aA<»˜Ý xn5€:B°º![ˆJ{/ó~b©ÁM*ök´ð¿¢µ]ðÍÝè“-ÇQÀ}¬Ç°Éž"DlK«A}cûyß?>mm>’7I%U“æk„£%sn˜Q£O÷üG#àhÿó2 æu´S¢D`‚+®{Xßr-øæsœ£¿Fû +Æ3(2æÒ¶º6pÆ4¨5™:\‹0¸}Ú²xÀI#Î.Ó¹ÆEGTbÞ 0ƇÑo%p|KL •”Ùª™œB2.IÛÎTÒï‹w7Ëk‰Å&¬\šT2 ã)c§T n°C,£Öb;Çüà‹™—â} Ƹť…°"›N dxÂYI1HôLͶ„¼õ®ÙãÎG•.*ñ (ÉI,ª¿‰×L0Ú©åJÒdq†›«ì&%TŽ_ðH"ä½¥ÄG:Ž­ß P=JzÆDiŠàæàâa6š-rÕƒV®³è‚#âé´6réÂ<ËÐXœ§dhD6áà¹Ò8§–¿oއ¼G#:Ýù­é[u i;6¡4Iä ÞÞ6¦ÃDÁ‹T†ÀçPÇw/Ó?cʇ ç°ù!ˆ‹¦´¦uvüƒg!¾SF!Ý3ö3ÛÀœÝÂàÃݲ~yˆ¶Æã@œ ÈãYLñí•î9‘´Z9-º!_qÓØëj¡ %NXµ’ŒÄj‘‘ª Ð|ÑjLS‰]êj3OÁ#é¤JÏÛy‡Š?%BÒxïd¨yŽ6ŽJŠï_`ׇi˜G8wè»S¡eÀ*9YJ.MÈÓ ÄötÃ0²Œ’OéA(+é…óšØ‹ì„Ø©%ŒCÂ\Åè$Àû×'G°ºj/„ÇѲª)öyÜÉëÅ›™ä´©—d-g–È*eæôGàˆ —e'ô.žYÓú †a^"ñt’ôÊÄrÁ †Õ{´Å_²ž)Ò»$›ëp‹Së„¶‘‹25h'øyy#ö&ä çÙ¥…™òiCñ£ò4|iaS,ÃAJ­5¾Û”9í$’hE@ükŒ‰EÙyŒ3L¨ï%jð¨®5!$1ÝK(Ž×1oÂtg³b³1)%±‘Œ:Û™¯Âx3]lë¾ÃƸ göüzÇùì>Cà(™ç·ˆô5Ö.ÇìAáã+gŽrhÐs+8ËÎJÁ ÇÅ”µ@‚“$++Nû†ûÜ蓉éEÂÁ]ÈH&«,á¦#¥‚$s™'ë€'1o¼W53ÙŠ¯£î´úÛk$´àÂw0@'_L~3¨%« ïŒQ±*S‡1Eœ¸Ð â¾$aË+Çä™’¹ Îzó /ðœÅì‘®eè¯7c Z öåå÷Ggfg€¼iDèÔ±ãæQ×rŸ¤•(ð_}% bO:÷Ž_À Ø ÆÉÖœgËØla!<²f«œvÜùž+¼ÚnáÈ+Õp¥ž.|ˆo‘TËC·^ô)XXäqÖ,ŸÞãö`q\D“‡u¿7ÎÈ‹ÞK å¡Ÿ¹í“wö÷ÎŒ¾³Ÿ/¤søþŒhZu!~½úQžSÈEág¦hHòÖÄá1ïvT²ül) ÔI£-Eª¤W¢Ux‘êç-¦£FŠ"` Le„ç-ûƒÒâËBâ#Á°qzæ²7YEìá!ÛŽ<áI€‹‰$,bX‘Ѥ³INq$!£‘XÆlc³´Œ~á÷íD\ÎÔ=ô%¾ƒsÈØšý){´|R(ñiU¼™¥‡æ†e[IºŽß3Öss‹-K––›"þ»ªÐMoNÒ—˜Ïîá.už:bTÞʯjÌñ8op5=(¬?‚·êªŒ:N¾–}v—øgªÚ6ønåÜ”áK³)±ß*wç—ÿYôᔽžÿgðp}þØïN'GôF%*¤Šò¹dLá;GâyTJ;/B"ÌzJ¤I¹•6ì†rF‹ðÙ†vAä1R sãësBð†f§—m–+.ž¶ÛA¢ Ó/cr”«%ü°ü¥#žâÏã4?òœ>6`{ÛñIuÂÌv4{ˆÉ“EH”Œ#»¡[†PoXyú–9ˇ愶½U•§b½áziPøÙjì¸üàéM³ŠRóøX³WPtàPÍ_ìÒVãÓ1–o±W [f¿ðª“âéLûênðôJ†NÐlM§3™ ‹ô;Ò¦ˆ~:ሓKc2XX'±&Ýx_‹°fö˜ˆcH_zæ½{å™ÉŽY˜Z1ï5êéZ ±>›JFýÉœ|È{i)ã¿ÚH²Z6‹O«„ò4w®U™Ñ˜°&òÑn¯è¹GǬ©•·ÉõEŽu²§}ïLB¢ÇQ&9ñe&“¿ øŒt€„~üÙª”è ý½`Ì•h8ñŽ/ÛºÜ6ʲÎÓåáù=»¼ñ‡Ë³U\^Iyv™%Wë,å‰gÙBèûÛoþLßä endstream endobj 701 0 obj << /Length 1528 /Filter /FlateDecode >> stream xÚ}WÍŽÛ6¾ïS=Q@ÌEJ”’ÓvÑ]$HÑÙ"(’d™¶‰Ê’CIqŒ¾|g8”W^;9q8’óû ™D›(‰o’0þútsûæ‘P\ª<žÖ‘N£\K.t=­¢Oì!^‘fì¾ÛÇR°£³›-CüåéÝíC•¼ÌáØšD‹Tð"´óí>^¤3ñB)³=Ž‚}R­1¯~‰™(Ù°¥•”íLÕrØVQæ[Œg¸#]{vXÊð °££qŒƒEA× fÃ9U»úÑgVvÚ58 ìr¦‹Âö®¥±6n¨l‹¶£¹Bð2 Žª»veÛµ=Zk²_{E”"•al;'"»Ì@!yZHÐÚˈ²”ÿ¥‰HIÅ?†µ³è)»ßš®Ýøûy“â\Ó'Ÿ•Rlﺫv8ÑlbR!ÇgM·Ž± Ðz4 ü a’*a”µ#‰Ö>Š-M0é‚/ ‰!ňØm爷ë| ­,^pœËllWÆÑˆ-ñãvAEÐé´æý”ε¸žÇv¼ti*Áóbré£i«8:ÑìÏqéóé÷¶6mohâ“Æ= ô[ïs˜.}ð‰&•xˆ ÉÈ0ûЭ”šü8“éÀà }+2f,¦4 H ÝTÉ”¡IÎ$‰x$'@F‘agV¼¢„¡((ȵ,©â…ˆ†Èg<\"‚Xà`%H7Õ`‚hÀ±„ùe ¹CÇ)Èú€ µõ.Žù^›=^ˆ**¯Ž¦ƒÅm…wL¾@NØïv¶ïÉ!ÀDÜ“*e B]û/MžÁ gðmÞ†£îïÞÕØ¥«Ü1hŠø‚Ä,½{¯%˜ùnêq¨–éQÿ"£LÑŠ5XŒžš8Ï¥£³ ]0/ü"i„3_GëÌÎx¯=‰ûXÏÅýò&¾=Ly ŒSýœÇ0±ít˦r«k€è}‰0Ø4!#ÖÄ%)YÿœÑ:d4pm{&¦f®™pÕ®¹vÝ.€Ä€ÿ] ³Rì!fádb>hZ½Hl»SÇ&>&½— ãÁ¢™H-ç‚coÖcMsÉà‚€7åEtÁu™O0‚ùÕxªFÀ;"‘³Cå\œaN ÇK *S.Êt:á nÉ(Q€éÒsŠ—2}‘vT¾µ…ŒFÂîö¥>)&ÀqT¾C¨a\ˆ^Úž”§N³3^ñz ªWKÛØkhxeÓÀ–k§r0j§†ÖôØš3 5àÈp¾÷®rƒ­Ç¦ KûÑyv×›kÍQƒåt<¾Rr@\cžýrÙ(”æJèü_ë •(®Ê—ÍäTa٬²y…ÁÄ…Ä®sµ2ðÂjð%À쎸Ó‡f¾Ê2õSxQˆ¤ü©Ò©â©¼ìj?ÓÕ7+¬äo1FÂ6¾b©ŸÀ«YÊòЩ ¢¤Ôñûè»™k|W”ì#:,ø4KNÚê(祖…]’ñÞç’ç"œœ_Ú„%Ð?Ô8颺 ÊTMß«[ú׬çúwðž»4häàEë‘<Ö%ªmYM­[]mÝAæÔºõEÂÞ¶5Ú ™ÊÏS'×!ßïUßòÝQ ‡Æ|Ø1X:‹Ïãoüaé÷;“TÈ2ðþþpç}zúöüötóõß4I$ðãSðaTïn>}I¢pßák|yð2»Hhx"j„¯&úpóý›DØhM¾—€ðuʹþ> stream xÚíš[“›6†ïó+螉 : Ãå&“줓L2Ótšö‚ÅòšƒC’í¯ï§øDÝn·^Û7‹W€€GŸô~¯¤Ð»õBïúIèŽÏGOž½ÂÌC4 ”ao4ñ8ö'â̽Ïþ‹"äWʃßG?>{EBO’Á­pKè 1 $ö4JùŸ’ù*KŠ™ ‰ ~Uè#ñ«©²?ÌE>Vå¤Îì5¶¨ÌÆöŠbb‹_Ïáˆ|õÃ`ˆ¤ž¯±ù`l|uc¿¨+[‰¹ûî-~ Í”ù "P& ÷âºpØ”®ÕMlÝ×*WeœÙŠM¢æ€ÞE!<ß°+h¬¤Ô"¨*Š\UB!Æþ»¾î&îK õ xù(òÿP‰®WÊÈ  ·TÊ¿=w: ÚF«÷Y·~m±VnâÅïÈ@M겄øÅ¯,í…Êp ¡ ­þÿo}à¶ü'P‰ƒú¶Ð¿¦ù­eçcÇ4‰3WJl³&Œt–3çÈŽÔqüP•ÅRmp4Tf'EV”1t¤½ô¿#Þ—öiäà¾7`ó§í8^L]ŒVúÄ]¦Ü™¸,M8[<µ´­P¥Yâó¸ªT™ëñ8ŒNk†ÉtÏ2ÎóFÉäî¾Âítª‹nÔC—7ýün¦# ÆCø[di²h‚7‹"«+劫ªLoà_ÝéÉ£BÕÕÜÛàX/8áÀýZXd³ `óT[r~vâ½…¦t„¯Ë¢žC a&Îß½ðf=’B¸x¿‰ú 0÷•Qu(;pÇ}i³åþ¶¨.ËZL‹²Jjã­"q‘µ¦FØØÙUgL­3~ Ç¨ÉøÍ€é¾sÞ»Óoóm¿<¤! "¼á˜ië˜MbWÓ.³Œáñ—k¯Væ;{]:hªïU—©#÷éIN»SÉÜ·~=‹oUWh_¤y7d AewS¦«iOgDGè†ÝÙJCõPn,øOj¢´ìŒçõ‰£u‡¤¥™ÒáºÂ}46²û!çs=-aÅL&mç®Q‡˜).ÙzE­˜^—iÓPâçä»úA³éeTïkG¼3ïZÕK(zîÙ )d¡yËYˆGOèßµò!dÛnó*¿­³Ø-¡¬PÄiz¡½QoSeýT|íµŒÝ‰À'nbtª¶pÃ陞­áþXO\IÂNfÆÊ€#=àÍ{ù=žÍõââK|8ëóô`UdN­ÓîS¥ªE—8òfe×”®UÂm%ïKµÐKÜØ¯bôÕˆ}5–/ «­W÷§xÙ™Úu÷ÊCÎñ¹&”bgçâ­Šþœªoz-‘¡s•Êûá-{x7ÚúÜÍ¿™Åå þˆBôˆ†ÉC³†ñÒŠÆãtegÂêZ#–ä|¶yì­Å8ì ßF‹õ®ŸfuÝyLn<&·SîÊ IÙ¬3-³ô)˜#Jj‰Nø`½nÕøë€iÿžzfg×™Uyøô†Kê:3 ƒ8‹s¬ão/d²¶õ¡¨ot&æônI¼µ:ol@s’a±€†ÂÃAH±­öj;ìi@‡N´¼hdòJ° Dw®Q÷N/ÛòÈ[)þe˜ØÉƒ¯fGKi&jÒòu&)dôÈ“?¼±Geˆ Û(½ü¸h '4õËZÙLze°§þÄò‘^÷ÊÈÅþëŸötŠF9?æibûÂX­j¢Äøì@ÐÑÎÌO´›®^Ô‹ª˜¥¶ñlò®CXÒ˦ß^²íi$qÀ8ñ†L· ±¾Œýrôä/Š=T« endstream endobj 788 0 obj << /Length 1226 /Filter /FlateDecode >> stream xÚíšMsÛ6†ïþ<‚!øX€ÄL§3Mb·ét¦ç”ö@IÄ–"5$åTÿ¾€HÙ4 :BâƒeóÄ ðÙÅ»»H°Hðëi¯ïo¯ÞÝp(¬$“Áí*ˆX #Židž–ÁôK8“œ¢Ûg<æèÓÎ\jŸþ"²ã= UQn“ÚÜ` ±(üûö÷w7q§o X3J±§þ1 gQÄŽÿpü‹:?޹âf¬ÇÆ?¥;ýó°_¦0˜q·t¦·:YŒÌ`#› ¿€Rßjr‘ƒéÞÎÁ—…X´Vyxm>Þ˜‚¶&÷&±F‰ŒE0Ì…z0J¾*Vá€#ÂV‘ÆuÞ,ò8ÂD²!ræ|Wêd;Ï\“A,™pbW4òûª—75œ„ãaJ"¬b"æˆçi½MvÀ 0•à ”¾l7õ5è·tàfú¸™‡®ï’µö“Ûõ¥‹Æ³XCõ¬aæ?ò¼=/j]¹ìan¹Ûõ—¯„²lÅ03nÜËh˜—–gÉA—lOØÏöQõ»Tr•ÑHª‘Ô02¥@9oô×Ö’Íÿ9GÅÜt-Ñ?zQ7/N#TW¶Dˆß€DŸš“ǯÊRî%Ûë²Øï&%(IŸõˆ’p/ÙN·#9‹…Í/ öwZÀ ›º`³~Œä^²½¯Fë~7jàô5×ýNEéƒ)Ž9z9x€¯õõ/ÏGî¬í9>µ}Ro&ä£ÈÙy) ø­*Võa|5Å:)!òÒ—S¼éóýHbJ‘¼Ò–ê°Ù´Ò2 ¥}Ú*‚9h?çÒ!<ÏÒáË›gùs³t8¨èÁ+[Y¸'w3wMðÎSÆ4\ ÷Š8Wìòù{ÜššâfX^‚Wb’%‡b_O:=Ôi8S§¥G§u6š–H‰Iìvi âu¥0ðå8|9òJ²×:ßoçºClËV¹UCð¶Âô4Áˆ€¦Ï8öTß]²t¥ÄdÚni.o)ï@†#áÈ,”gm8…¹'¤a$ÌQb!œ ¹Ø%‹´>LÞÜ!-žôæ.iêAz]&ËTçõT‹¸wk‘.cæÁ¸N³4_OYÛ0kgfm”{àÖ«•^LI²·<74¸ÿ¬7º´;‰€ªÚ’:díNãRÛs‡yZ§EÞn5†3в67'²•‰¬T]úFácn½ãš3™¨3f(Ò¸¡øÞ.(0ôiÕÒ<„œ¡bßœÒÜ$öé.|8ù¯ôrx¶l^Λw«¢4ï™`&•àÇ#mf8þõƒ ‚ }®ŒÜ4= ÏŠ®÷¥®šÇ4oý‘˜ìÑô,cÅ]=4=Ó}(¶Û$oÇš¥ÖÒycrÛO±³îÐvÞ6d<Á~nZù¶¹¯›w¡ ØI™&óÌŽˆ‚2­|ãÐj릇VEwHÆKΞ¶ÂOcB¼ímnèm½’>HÖ€¼>ÎØ{;Ù3 Ê»PÈŽ$Doû¼°'åàä­Ýésm ßÒª.ÊC3/îçQ²°“âß¼°—¯™^®OóÄÐf ¸BÀ]“òÆn°H3v¶õ¡L×›Sc6ÛL"Ý;½1wç׌i2„Â@Xû›ÇÇf¯o¯þ­ˆŠf endstream endobj 692 0 obj << /Type /ObjStm /N 100 /First 907 /Length 2624 /Filter /FlateDecode >> stream xÚí[Ko¹¾Ï¯à1¹pXO’€±€Q6@,l6|ðÚJ`d!¶ 8ÿ>_Q”lÙ–º×ÛSöpØÅÅz“òÖSIÞ)uKR4‘PòÖU´ècihk´šÄ{ª¥$åøÞ’á÷Z8yµƒ<Ụjñ>Ævºø˜NcŒC1@ðÅ$Þá]¼*cÜ? òOÒ©…šŽ?ÿý)¤¢þá×__Ü9"Ô$¶æÖ¸ÀK¤ã ôAh¾qã7aÜñ§w¯ž]¦S,êÉI:>?ûx™nHܱZÿjµÐÃï\-,ؽ«ý´Šß ¼úxÿMÀÏÏ/@êt˜ÖÀòÅ”ã÷ÃñÙ‡_.Ç÷¿¾9ÿ÷áøèâÝë³wƒ4½8þxüËññi`)/Ì+¬‚ªg‡bi—\ ǎB³`~2tã.ürdËm¹†ÒêÄ%L,QV®ËHx{$Þ²CA™{†^XESiÉÛc@ÓÅ¥Q²Xcƒó4°ö1Ãñ¸-ÚÖºƒÃÂçQj0ñ#CR¬ù2”í5˜=7!ìMÏQ/f-¹ê ®l¯ÁLcƤÂ#¢.-CÙ^…¹ mq`™ñ.-CÙ^… átñð;%S”ö{„´÷p¶O/ÂëÁªÂºÊ§»-×¶ƒê—Q»Aæw|³•"ËP¶WRÈ+R.”q„*º‚+Û«N’AÚp=€Vú ®l¯:„à9Î F¿dE,ŠéËP¶ÙˆŒJ[ä\qÆ%¹T^†òÕ!‚.DÝg™„TkÝA””qfýõ9Á§€ï­ì_¾}VÙoþ½•}•n•n•îy.§™WígsœÍqv=nVÄmVÄ}VÄ}VÄ}VÄ}ÒóIÏ'=Ÿô|Ò›G)qâ:Ú:éÕI¯NzuÒ«“^ôê¤W'½:éÕI¯MzmÒk“^›ôÚ¤×l > ?+s0kqZŽþog?/ß¾=;ýæc~¸¹.¹!=¿ò>Ü)4{I•né(ªm8Ò`lu„.×9™ÑÝæš]ð /¥ÃI\4ArÆl+áðp®:|"²ƒ9r´{Šú·ñlïšœà°a{;’"t˜„VΜ)‘ˆEÌ‹°[â{G¶ÚW±†÷ÄüØš~È:‚Ù¢+íÀ!Cf·¤®U˰‰ªk9´ÃaŒ3$$JÙq|qì ËÒ#;ðÆ =qwëz³œÀ«u¼‘]¤G¿ÙgÒ£P±¦+í!=‘°ÒY„€Hy?·•€öØ2¤mL܈3ÇQ„¬¤;ñ¹|DŽ­åípjT :‘jð&Ëúµo´"ðŽœ{ú-mÈ5Ë:Þèú¥éávãÙµÖÜî)Ý´ƒ~©iŽXöZz4Nqz] hýRåÜBá™Å!—@¬Örh’2ÚBÛÛZÙ€¨å^À!8²H`‘µòÏÝ8.ç.>–º–Cu{@õ¬^ã’t”,@bZ ¨íyVQºêHî+õE"ˆ¤ýšCÒûÑZmyª~ƒ(.‘ɧœG"Eµµ,¢lµ€7TýFñ骔Õ<ÚÁX ‚•Oi˜¨gü­E´ƒµÆNeSÇ/\N¡¯¤Ûë"Øð¸šQâ¬wDg7•GÛŸNÕžãn*öqÛªÄ šûa<ÞÌMT‘‡ÜÄ‘C܈»ãrâ Œ';MÍ3:äÆÊH. ÉÅòíÄ'{œ’  ŒÛ‰íê–b\‡[¾žød‡›£0·¹{üKOËÜÐ2Ÿ¥"ÜŸ¶? ‚hÆ¿‡`·qG±uºÆÉ—ÅìV×þŸÁuiŽÂ4­(LŸZÁ*Nãf)K„|ýùY–r«W iÚü¼êçŽPzµ×@Dßþÿù¿û|qø/êÌ¿ž endstream endobj 812 0 obj << /Length1 2346 /Length2 19834 /Length3 0 /Length 21194 /Filter /FlateDecode >> stream xÚŒõPœÝÒ ãîwwww'¸ ƒ»Kp ÁƒC‚ î.àÁ%ÁõÎ+ç$çûÿª{+UdVÛÚ«»÷~¨ÉÕ4™Å-Aæ@“;3; ›@RYB ÀÆÆÉÂÆÆDM­eëîü‰Zèêf rø#BÒhæ¶I™¹ƒ•AN;'€G€W€ ÀÁÆÆÿŸ@«@ÊÌÓÖ ÌP9ݨ%AÎ>®¶Ö6î`žÿüÐYÐØùùy™þNˆ;]m-ÌœÊfî6@G0£…™@da t÷ùŸtB6îîά¬^^^,fŽn, Wkz&€—­» @ètõZþ’ P1sþ+‰ ecëöCdåîeæ € ¶@'7pЇ“%ÐfhÊ+TNÿ+ýÀø·9vöÿ–û7û¯B¶N'›YX€Íœ|l¬V¶@€ªŒ‹»·;ÀÌÉò¯@378ßÌÓÌÖÁÌð÷ÑÍ2âê3°Âõ¹Y¸Ú:»»±¸Ù:ü¥‘õ¯2à6K;YJ‚NînHOÊÖhî»ë¿Ãµwy9ùýYÙ:YZý%ÃÒÙUÛÉÖÅ(/õo Ø„ôÛf tp³±±ñòð€. ·… ë_Z>ÎÀ¿ì™ÁüœAÎ+° `€­ü’Ÿ›™'àîê ðûÓñ¿‰`iká0ZÛ:!ý®6­þÁàù»Úz ØÀëÇ`ûëß7Ìääàó;üï³J*hËÉk1þ+ù¿N 7À™›ÀÌÁÍ`gçáð‚üoÿvà?êÿ¶ª™Ùþ{º?*Ê;Yüÿˆwï?B<ÿÝ º¯ =àT@à}è~¯¿!7›øûÿçKðwÊÿ¿Ýÿ«ÊÿëúÿßÉx88üí§û'àÿÇoæhëàóoxŸ=ÜÁwC¾!Nÿ7TøÏ…–9Xþ_Ÿ¼»ø†ˆ;Y;ü·¶n2¶Þ@K5[w ›–è?Sw°uªÜlÿzpÌìllÿǾsöàGÅ <«¿]@ð•ú_Ji' å_wÑ?Ëö 'X x˜fŽä€õZý†à VÀ¿œ¶¿+rþ=ÿ øËòpý£8Äúî˜Í!¸c6>Î6À?%€m¶@ð¡íþ€àîØÿÁ-pø‚ûó‡ðcÆú»278Õ | þðƒÅ~œ ú7XŒóo7ø ÎàôGÙÁjþÐÊ>ºÛo¾¿ÐómÜàp7ðëü;\ó÷4À¯«»+ðv‚¸{þHkðø‚å{þÁ ¼þ˜8û2pyŸ? XïouàJ¾@רþçE°ðpu-ÿ~³ÁÏÅðߟf Ðh´´² ·«︫'òbÞ›ž£ÞÓͤgö[rýêñ€ŸF_“ºáz#ž6Ò‹±º#Mw-¶LöìwÜÚÙ–¢Þþèÿdò^cf¯iqúÍàTñ±xà "1³–ؾÿ³‹¿Nˆ=t+d—u‹šZöW¿¬wÃ@åÊø»…=õýEä§ÊYæxí8òoÔ…æ¹óøpîÌ$ XÞèß®oæ°ò§^ÉÞ3"œÄs–øéor$ÜÏû®Ukq¸uPèã“@_cÏÐøI¤+à}÷+/ÛþžÇ8¼ÞŸ<¯¨C@¨†ï^Á,ü!X© ›ª;ßË⃫ƒŽÅ” €†–¬Á/‚º\Ö*å3åH¹I.±mÐý3%‰f²¤%ã×Òî“3í.ÿäD|öø“ޤ7ÂØÛ¹fĽ…EšØß·ªK¿Èöƒ`žJŠª"+ßÅ F…œø2o炨EUÞÇ\<÷“ô/A†™½(nä.dT ÝÝöMRò—¨b†¦"¸o¦Dq|zIm!?´«á[Âå‹®D ¼ª ·Ç-iô˜–ÌTäw®×¢¸YÊeJ3hß´0¸í ÎN‡hYò“0Û,ŽÅX6H7{O•n]ÏÞþd…oxÏvˆÈ{Jj¦1eŒI—ý¤„g‡I9FîèµÎÑNÙî4æºEåû:£…uªŸšb4íW¥WfúúÀ5À"›æ…ý¥zwÅ_íŽCâÈzµÑë—¹}·Lm2rˆJu™•`‚¥(e’#ÏII¯5Ô~¢ßý5&ÃýúÙiÁ 26“¦ú.Gi{Ñc5 m¹Ó'CÓz#õØð0´íµÖ^'6sþwŽF—LǬËå%†o©x C´¥c([â” UOèP§êY¤ž¶”j¶+ñ ¯¶Äî|9iËJi¦ÓxJÃ/82Vábº¨aéÒ®²íƒMëñ¥6^X뇡Òìé°F’í31œkÐÜMoŒ%ú"ñ·çë åBÞb›ÜTŒ%7¾à"õ…ÔWSR®ÙºN)¾œ&7}Ü} ›ÌjÕhZ¯`ØÁúôèWûd£·ô 0®K×°|´çm"›¼rùí¦ý ðA´ý_è1]‘Ú¶¿Ì&4äËŽ,Ô@•Aë~ü‘«Íƒ*+پř°þ”§÷—mKc¿¯&¿‘|2ðŸðþìÔ+éBÙD©eÛÆ‚qe{§ûõÒv!LTÑty$¯°cé™è5àÐZp²ë}=zuŠXñ×8‘¹šàêžãÇûóŠG'þqö¬æÈÛ½‚GÜ Œd(ÈêÓÔ>”îv¼ÈœÊk>Û¾¥áûL[¢úÍbû8j¶"¿v§KÎOV<£tdæ Åmìë@™_>ÃnbäðÁÁAeÁœŸ3Àu ’D«Èª{–ñsAù¶¿Fs}¿u A8ñÑ“Håm˜ -åÁ¿ OhÓYï]/Þ¯Ó›ªrdĶ>ã¯øšs²í ]3ãkéÔúuÔ Þ™È'ÅGt±$†¶·Q3Hž¸âT.#»ÝQoZEDº„ùeœê)ÓÌÙ´l>3§øù ”× º6„µ("^ÃÇ,÷ îÏ«œñ©Âd }“‹m0xåè½ þÙ[u"Ü!òñØá•¹®Í×(Þ6Ÿm|ÈwìuÆ4‡?óFÊ#ßiÙ ›i¥\㬎GBnÃè>£èZºiËß Ÿ=Ìea(ûÏÁf¿·T¸3|[©V%ëŒÞÌeI‡±¡’¸CÜâGñÆáÞ0`d?ü™O)ëòüBü\XxêÎõ ³ktðçè}M¼­&þ)l88ZK~ÿRÐ'ñ%Ïœ/xºuFu!K¹¢ökcÜ'¬Å²m,[$ç„ÍÌXú!×ó ”‚ÀÝ5ö_ÙȽ߳ᅃ,™jŒçxJö¬r™Ôº'Ëý/>Ûwhðµñ6]‘ŠØ"GÁE}©Œ»ÂrrUf‹ˆÅÚkm°rMk $d";×™”¨¿9jçt`7Jƒ;¨jÉœ@Þ[œŠŒëÞ_:TE=qÏ™VÚ‚\/±ñõyêpv­¿’ÂÞÇÀY·G’Ygl€ÖWQÉ©I´ qº;l¢K*ÚWé¾å8®Z¿ç7tÕ…•1¶7³¾ªâLG%OšŠ&èº G° ¶Æ£4Qìkr\ëýœÿþóMÎéC×a]v”ž¹™dPjÉ46„ÏÎBô½ÄxÌ…a§Ø²uÈaÜ”‚¨#@ÚÅe)5üŠËxaft½kF*ÿ ±Ù?/ÊNqK÷´ß§‘²XUúä&¦Ì®ËK‰ çí.¡ðóv‰—Úc ÝQ`”$!­g‘œÌ£”Úú] S‡\Øq÷óCWªhè4( ÿøÄ ÄÝü™äTO}²5U‹ýv0ÍcØ}!(t& k°%vGÈ…B×]ÂP°P¼üÖèéãGXÒúk"+ü/9œB¿£wÚo„ºÆÍ^”/I`3Q :ƒ1ÏÜV¾·.n¢›Ìtô?N΋ÈLÆögÄx&«GŽØ¡ç¿`B%?|ÎåÁ¥Î³†¦, lJBΈS݇E…BÍF¿¤5[ÒdÏþ9Œì÷Ê { ºÛRàEø4z%1¥6…"J^”$nk &›v0=ÛQ„1. W+ÚÇ£ªsãEçŒÊ‡UÚ=I¿»4×¢?C¯A/ ˆ× Òäu¸æùذåO…ÇÂu” 6ç&º‚d{5å Ñh>°mèŠÏ&^Õ·©/tïÉX9 W£$¹Ûž6ÉXN²Â•ˆ“N|ïËâ-9»4˜OÚ¥]ž°d(¿GåJ–;ú0Ч`M„’Û½%°¿"%ŠOX1 H†§û𓳇%ý„„;^OÅ”uåák¹<¿ég¾M\ôÄØíþe,)¥Ðq“ù–‘ê‚dO³£Mͽ A^mêq{Aè% Ó3wûâDéÞ=ô¦`Ã(9 ÔÁ ™¬£S=ŒÚHÿUŸ©sÀ=uL›*û.O.ø¹âHÜC,EݶÉ\¾ËòÔ ^NìÈGÌù·OÆ‹ï™OU–è2IçSX~½×µ­Â5+ž '†ô +%®" Ïч檜5«`Lˆx ®£ •FåX°ÈLU1’&ŒSK8~aæFy“§™ÍqþüŽár@:uäB*Ø5ß>ź™ÐÆsdPŽ¢„±p†jé!jÖBù¹ŠPQ(Z/"Üq¹Èwñ%†*)/ßr/–†’lt—êîaÐ8§>1þ(­=DNŒ?0fH¶žä†í%ýú뮺fé„§­J÷{<ò;lu>DÔÓ!još¢2¤…«Og6Û›2E†­FL»Asub®@ºr4™ 1oyŸ–â—M‹‘ëœ5E©[lýÇbïÝý! nߘ Ýñ* ßçÌòâ¹L;5†Nc|™©ôâàZÇøÑmÉj~&h@_soÍUVÈyð¼&KÁê¬ÖKžF²$ø©Ã=e2C2ßùàåç¾7ÀK9“±dª:ø#‹yEÆŽ¹þN‚˜Plñ>jèÍ‹¯Ï‚Ã7ú×gŠzÀÊŵb!öÔNX÷š¶#h6ë a‰£Â*#€>8wç‡oʦfÝíùõJ¸Ì=b¨÷b £"o÷@V ÝgTk™÷§ôÊùöK·K´n dcѽã[‚_Â?€;,–Ô(ûl"¯¥‚Ø]‰ÍÍT»—Æ“P"LosXHdWS‹!³ó©!SeûðÚpì:™h ÎÞhÓLjVW²¡eÅUej~š°î4Üié}ŒÉ:^›a´ác‰Ä!)k}ÿÊË80>rU˜yn)9¾P(xsL*ÛßYû1¸xp@ŸR¼1¿°¢á|è"Ý*‚Õ¥¡T‰ú¬¸(Få¿$¥û)+vîŠUM¥Îx:“Mñz7ä°ÿyu°™>`ú³Â¡²5Å,÷ߥI§u•¤‡d/“bn>ú|ž(Âdûä}Á~Z×:ÊÚ*;%d/¨­*½µWžLÏ"Wív10º™ðñÁìgè®qÉ×3îÉ\*½‰jé². ß Õäóo\P5Ký‘}ðc¨Šº¨KHÈk»\Ø^4uzåÅN¬ZÍŸØþæM×G™—“wn zÏ}‹Š¥veY¿,œ‚³ø„ºÅv’z29¿|´kÝãÈ ¥NƒäçU™¼ ò L2îí‰qTêSRÙá¿õ‰>nè!xw‚0ûN7E¦ýD/Å":±±Àß‘[cÅ¥qÃQyž0£×Ú:ŽŠàEIŠn¢áK„ ?îAï²µéxÀ¾A»Fà´ÙÑ<ÙøðC wSjt ÙŽžaî¤!…z!£w/IÝHè¨Üj:6pÁꃰKÎ×f…þªj)rý•ÎyE)¢‘Y‹žÛ#º=¡"=ü¡$|–ܲi¹ÃVTN¹7QC ‰×½Ðj¼wÉi”c¤‰Œ-Ú[U$ZZ[tyôd_ž¤-W¨»)~¾hƲ(TæÓøóºDzÍË>,~xÈ£ÚÔ‰žQ)ì\|qpœåqá0”´™×¶ 1ÑuRL%fÆIßT€ ©Â{ ÀÛ@óm‹·boA±Ñ—AZã~tÓDíFŠ=¢!JCýϧ/ªRO7CYg©6@²bâžlb,׺ë ÂІiØpqáüצ!kÿIðJ£^î'QždÐÔYß–¬ÉËzpÁÓ‚ãE ÉM]û‰Š9ÝÜRnú¹Æã7©ùŽ<#æHÈÛ]µ_Vô´'žO\1SU=Ò :A“ü]Ž%‚PQ'®Ih®PäñÀ“‰ÁFoãÙ³°U•°Ìñ¬Ãê÷v¼º¥G”f“áæàS¿6Œ µIèÈÒmÚîâìÊ—éŠ ‰µì|®å¹­Á>´†ÀŒ£BÕ•­8Æ* aSqSâ¾^‚˜<|¯DöË#†9’gÁÚÄó IiT"]Ó2X(OߨHΩw9éõ BIývËï¶'Ó}˜ÊBtc1hÈŒP&ž/žÙC Á©Œ>‚í¿V¿³,®p¾ªsÃÅ6æSdÏ|ôa°fM=ï/_æ­>Ò ÙâØ §Zô?ëz*–  ¯|òÖÓ¤„’EðÆ"'t߬bÎo!—+Xl Œ0j’v…µÃÑ2œÍÊ6`(N†ÝŒh2jV¶rìöj6*ûœ¬›¼ØÝej|ÿ"t¾ø9Þ:àÊÚ\Õƒ÷Á¾gÕ‡dg]ñ#nR/‡[S•R1Ï€å{5þþ•ÅJìOA¡–­d0}õÛƒâK´‡ŒÄ|b>>êšÇ£˜ç©Sz¾/yއKœÞ߯¢mÉã?¹yÄN'[Æ6, »âKÖé‰þrèK× ÒµôY[áV@Oj˜9°_=f;ž¹CÖlk·Ñ\SlݧoÁ… & þþPIÖäÐb¾åvATûây, ï×hJÐt~™ÿ†RY”ùþóÛuë2hþŠÛé Æªë„y˜ÀÇï¸^›NhdË‚è­i€C1ñEÄlQë„^•÷.ïŽ2`¸ êù0èûµJ&, º±ÖÊ354[§G'Ží¹>þÂYÕDHXäJ_9m:ÊhjCMÆ&‚œ¯0_­(¸ÅÄc‹ö/Í]pŽ ˆo:utTI•?¹//0i^X› ˜5°EÄ|>b–Õ›¿óm8`”õOF(´2Iv5’–}¿²aæ²’“`Tæˆ8oÔ¤ìôñ5Á“®VªžµñjYɼ 3è0ö»åöù’Æ'ÁÙ¢¢f }:Zè[/>Æ+Ÿ^›­?:nf›ÖësÄlMGùÇÂNûíŠ+Xd¨kÜ£¸8YÒ­£¯äødýl¾IM˜jU*H&¬þ’‹ôÕ0[½š#Q{ªþø=ãûQô¨÷`ޤXûK\вó¤Ab<Û”hù3pHJ_ëè*‘1¢BàÈþÎz`ª,þ7l/Õ 6¢‹¢Ò͸Î|ᢶsci‘aç)ˆàåÄõödéÒÿ³€@3†¬J’„j¶/ÚȪœù…™l”ZÍ)—»RGF‚9dR‡ü™Š<¾äBŽK“‹b&Óà'‘`Éd$‡4^ÚÊkÖéÊ£’Qh¼å½(Ó}i_…˜;Z¬=Ž>ÏÚac›l˜×ZSѽ‹+^9 1kW¨òö lå#öpn*òGmå>¯%x¥2 w{V±Ê¥L¨™Þ<Ô®RþFÇ7Jše.Ý¥~,‡µ‡áÎÒkÅóƒðd¡°Og|e(Ÿa¯Ð{'h*_Õö{’i³+«¡h*ZS`œF*äVXLñF|#«¹t7ïåšµ‰œ£êRfUe9?‚ZRA'!|Ë#¨w(m)md9|ZÇveP¾¼Ÿ/OC[³Üç ÇÑ£Sœ(u(Hëܦ=ÙAN$tNÁçPß##XHÆÞËŒQæ8Í0zTDØ/“ÄOh þÀXJn%+&ÓoÆÑ~¾YÖÆÍüIW¥ùC>VŸ‘¬K%aGO€3Šó's¬h´ä1s+î ³|’›7,r?}Òìwks3yì¿ö¥QÎbê`+"r’;df£{¨¶‚”á„a¾o$zgšVqç-j©ŠtêñD3ZÇÞ]§ûø¤~œðøÞij{á JWEzL;KdbÕzÏšO¦4º‰ñ9"Êó²;:T&¢5!Jd"D),VsnIO×-©»…ïì#1ê(cÐ8¬?#I‡ r@Š÷zhdÛ"7(qŒ¦H.'k9‘½Ü ‚‹wˆIÁ/¥&‡™Øy¯–ùÚ±Ž(YýžQtAζßÞYG³Iá£6µ}œf,3£G} |›îQçO*IÏ>ÁñǃBõø,†ÖÀ͸­êžÅ‹]Åú€qzŽå Áô+fOzBMòÖ˜o—h+U‚¢ç»™K63Q~’ÑzV7vèø‡24>ã¬Ùk¦Ä‹g%Ç×M•Ê>øDӷМ* ¾ôHª3uN‡ãƒ_¹JÄÆ‘#Ì¿á ÒYÃðö#‰ßßwS_rìnâÑšiÀ­;§ìGä<ž–È¡U—"îv?›´·ÒSÿÔÂÄÉmªg" ѪÂHT³mäù”êû ‘ÛS¥àÃôÅ¡¡món'1T™²tþ÷3Ò€Ñæn}œ]—ÖÁZ?D³˜Š Aúà0‘Åë"®müpŠì¢íÓ¦^NÜ,UÚ8èç¹,»ºøQÛÈ¥áão<#X¢è¯WºšEÄ5ä?{ ÐŽsºÃq¦¨Å¸žR¦y¬hùs³¨©ãsNĈïàð„]ôbPì`mÂ;ZÒ©'ØT½”n¥„³9É!ç”Ü­#a…:¸NÞÍŠ#ˆè ÓV¤bÖH³²ÁP5~:¬yã©L¸÷¹Äƒ*ÏQÞb8æ,ÿ‡¦¿h¹EŸÑ/e:oû"ÞZ?D¥NÛ–Sì>…H(£÷JhcbÍ+•ÌgC~pUJ|Î^»z8C{r }Š2Fâc& ´=ðÈšNJw™un|%õ°jYöÍAîhì‰×4Eb)­{º0ÈË}~ÎFD²®‡Ü•dÜ—ŽÂב‹¹Ynþè>ÀŸ•(ÁŽ©ñ–@SRr'4(W,wË%‹QÌ3Gq5¢3[-í-u l'°ˆ\ p5pž>ÿ“3°JÕ™œ,U*1·æÙA§jŽÍP¥¹¥!ÏŽE ôiVˆ‚Ã’—Wt‡äACmÅ60"Y>U ÓÉod×ãm²’^‰4Ц¹Þ°±Á1¦¬¸ ©ˆôÕðHR¯QÛE#ÒMaµ±!-(&zÝõdq½ªe1¨c¸Ç{ðz1ã£áòõɧz|ú Ž Rv c yáØµÔߨ‘²ãVm ÏIŸr×õ@DÌ7¨‰ D’ Z$ç–ønfÝ—sX_{è«ùa¼d—(f\Ç€G'ô{ÿ¡Œá$sF!GŸÚÃçåœì³Q±IN¨ú«‚ˆO$l. ¯‘sVM£ˆQ‹YfcÜž[zúµ ¡í£_ê¬eTÇÃÃè;T:F+h?k5U-þˆ|/´–qj¯K\Çu£ê±^p¶¦R»4I·¤) ç—.Â+Ô [ ’¶ëfÞ6·gi v5܆>’äš6[k „Ž–·ÿ4÷í‡/,y1^$2î—‹#ú\”‡òlû’¹›M8R$Š“—=øÝì2‚Ä»%‡ÜAA.ŒgW<ðíìÐ¥Ù¶}ϳ}m¿äk„ü¾ùàZGóæÖ”ˆÓ±Ÿ"zÏ¡|¡µ¸öa»—_ò^4›Çs‘³Ôêb2HjdGËAØHÂ|q‘à$‹W~kß<åWÔ|&¦º/Ó‚â®Ë”d€9Š)°¬/æ±3®ý™±£yÖÿ<"Œ~6ôÍüÛÇWɸ+ûX¯w)Ïï Ù]òí§ª-!3ãNaÞó™2ß4íÍH§·+ˆ•³­Í%ß‹:lÑ+š‹“:Þ(È熷à.ÃÞ艰Ÿ àö¶-9 hÉà:tWëp¢Žn`‹^Ÿ8©œ"ÎñJW”¾À\èÐd²U8”R¢£`©ŸÛ;ä*–¿¶x@FÑ1‹ÓUîéUwsΈ&Ùq’ΪI”ËŽ4]WÅ1âìtW÷jØßeD}Q#üzÔÊq1œWó$3`“®™Aù02-”$e8æQåy9†JåóvÇLd¾úC¯¢Ô‚!ë´w·HÉ`¾G6›l?±ôU¯kq¹»£×¨vî|yÚDÔZæÖd†7!\SœÈYÁTàÝ .&ý'ݚܩԽ²wêÃÃüÄX.Ù}Çvž 6™lPùèéã²ÓrbÝ󸜃J«$Ü™¦ÌLö£ñꘊö‘ÛiCßÛmiÜÈL2ˆK¤7y ¿!ýÒ];ß»<_¾˜¾>¥Ay*^Oú]Ã'ªç뎂ǰÀ%Õ4*4á3O¤¸àªâ±Ü‘ìôæ¨ã„‰¤'Ò™bHÐJì”ôõû¥G®iI…ß¼sõà§_¬fŒçlR;f8’M9ñ«ø½‰FE†4ið¨~m½››£ó)¹–;¹5È„.…J‹¡)7&ZÍ^Ú€Úžð 1"É$FËå]º&ÙfŸt=ó{*zÝšûãׇãªá/>-Šo"§$^kcöô,ÄXø&a@Ú0ÃAlp[™2êp´ÌbUÑŒ„µd““:jÆXS,Õ`ÊG`½A­s³ÓÉŸ|LUÑùy#ÂpÔÑÍÇó±iËW9ÿý|&K0q;…rÙ<õꄦÓÍwsdpo§]dÙéèáæsQ$ÖöX­üûR.âžÔ¤klèùÕ‡tEñ"bx7Nè±#°ë#Ô(¦\üC»~lÏ Tê°Ñø—&lèv‹ûSµ³VCOë Û§¥k×0ªªÁ[Kµo¢oÞK^é ›6E}šÍZדK¦ÈEß¡&.wµ“9ãœku[Þ=å lªš[¦†öĦ0¹4®”® Î&,FnPË-xÌ£O…ˆÓgÞ"ßéi‡Z’Ì”ûÀkΖ_²¾†X[Áw+:³qö¢ÇxÿÖ¥æãó„›8’ô‚ÿç0&ÖrÄÚÄ:WQVå”Ñ‘žhDq …ÀL«¼gP²+_Ø!m#}ã€o|ð,IOÅp \¬Ö-¥² äÄFÃ7ûŒ:“øzFÜš;á~}8Í骚gV¿·¶42 ã%Ì¿é'ÃÄxñŽ&$CÚ‘ðë-ºÝ²ÄÄSc°‡p¡ÖŒˆC.ÌqIê…yù‹z,wªùJ(Ï wÜ‚J¥Í€\`qÕšTü|JÒŒ• {äSêÜ\ï€ÈƒºþK“¼?¯nU‘/„ÎÄ +S”¾_8…†„´&ç¥WCn"~Ãj[½æ&6žÛ¯X»˜ªÍ,´÷ìÐéâýeΠ´7–£ B‰ŠŽS÷¨ûks÷2·½‚ƒ%ìzÔ¾ÍìŽn¦}1¤÷=BžÃÒM-[ª<Àj5týY;gtÿÅGÂX˜‹”{ö_H6aÍ7L“ŸØ «ww±7Q”u¼ùÊï\?Ûðy%H,M1I±ÖÕ¦2Ð)@0uÑÅ51… ý¸…Äjg¸"b‚`£ÊÚáb«¡4 ɪ,­Êür¾àH_S7y“ůöUÍë$?x Õ®˜)>AÔHÚ¾AˆoӉ׬†… ±n µÕÔ:»¥B‰¡Ö‘ºêŸšZgÐ;pxm4˜¹7=ü!yáуǦ]ŠJòTÊÆ,ù•ûÄ£u κséf;Ãf}áÉÑeµY ÂŽÜè—ô¼¯ß´‘µç5˜?Úì;eÅöòß;R-õÝHÊ5I¡ñ©ãzHçQÑ7=tk''ùpnñØE#îEî åï n9¯ã½TéCSd žf³tC¢8'gñUõÍ”³'CC9;âr:ßDC¾urÊîFoÑîÚ1€zÔÉo À¬Qñ™ñ¼îùºEN+­Ç7sýv+~`D;{ú•Чxó£€èoŽ¿rôÏÒñyÊ“ y®„Ù•hš‚tJZ¿RsÒ $½ë QP…óÆ¿ÿ*!h8o³Ø§sJé­þ†Ò«ñm:öHј"ÓæWðulï~óŽë‹òó„dØHvûƈI?øôÓBKgvÎ +å­ÊÒ™òä¶ŒÑtÇ=Ãîïf®bÚ?ø¤Æ!õ{`¾³ÕÐGcÿ ž¶²’2œN]qç'7­lÁ™»¯‹ÃÚþ¸²ˆô!Dk2×¶¢+—p¾Ða¤®¡‹Í¯ÆnÇ-ܾÖçtñ§Öw¹™<+W ˆ›Û¨•‚-_I¢Fkâ5t{$Yýud±dŽÅ”¼Ö…©Ù=Yb­qîY—FŒ nRé§B¥K'ÄûØ–7a?&r;î 7&Úp4D8í *hö3â §³^ò¡>‹D*Úq$"Xý\d^nQJ3?r üL¯E„§ì=™À5¬¹g-š™‰ĨûÜûY]Ž5I•I‘P×_˜NÚ\lÙ¿qˆMLURaç®ýdÑ3ùÓÇ7.¾b¤Q Ñr¨ß¯€Ž½öm- ë†tX‡BF¼ýóºž(éÀ¸d»àsK±¹äX›w¿ÂÊŽlË\Ô: m{Ã2ÙdxÔr&¼L¤¿s1^`SùëÐwS¨ÿجˆ/=êîdaÊïF¿cKc«­ÔdN>¤‘ªÒ›‰95¼Å;ÒÜw:H ̯@’‘øl¬´¦ãDôEÜ›Ùp›y\º%ÊÒôºîCT²O¯K0ÂÈ/N?ë2¹ŽbоÞ±¿Ø[{'Çp¶}¢Pywt·ŠYöÚ£á”{XtV¹·u§OÞIŸÉ †ÂÛŒ"„ų/ÝS|˜ªn>{¿-45ZŒ&¶8§ÓË®ñ…!¯Àć³ÖÁš‰”XÖC½'"ís:ì¢e1 >b¶³Æ.êýÔ«ZŽG K×À²Ï+ÞÆ¯w{Ý´i>‘<·O±ªjð‰6šŸÈÚëyê9£1$¼Â=Ñ–R¨’VêÆÅX¦xc åÍhÔÖ>q à-ne,<ë±ã7:$c¥ ~ɳø j±Àb "ªà‹®=‚»EØ72°õ QsÁhüþÚÖ¨Xd– 7´x'Èœ†¾•5e)_D7Æi¯57ý'ÓÝùH¼á÷Ñw»ÕÌf QBø×_0áL¹>âA¢‹^z>ðNì]%¡jÕÑ:|ùc, Ì6çòeËoRm4oÒŸZÚt¦Ø\Ö^Š-{ ]+ÚÀ6.¸)YV"¶Ýf¿<î$Ó.…)È8’ÇpKWPÅ9e.÷ù¹lä·,¤_Aãù’a„øêå;ñÑVG qyõÀH&êº>áËZúAˆÕÈ0…]çfEÄ÷ïæk“óóÓqÕg—JEÅÕüú%­c‹CUËú“…Íù§¡&?φ q+ ?½¼%(@¸þa—`¿’}žK Á}ªð> Ìš7‘Xuµ(2¢”C=ƒÝɇ£@ü {²¥,­´|n=»;íbBïb Ïf×кýå—WXo×Tc®…mF,‹sŽ)ññ¶¥z{õÛL“7ÕÇL’Z‘ŽbW»Ð"õhJýå»u]úâÚqz8£¹w„_»5+Ç–N¿zúâùG§%YÆøëìl98Ûœ®oZÙ» ì½Z¿¾&Ïí9iz_Q6Â`÷Ænàè¶ëkè}P¥qÝ@©’°~†DbJ~‰­ƒâg5Ÿ:Èn(KzR"ÇFÏ[*´¡ ¹’–R¿ª£Xøwðc-øÙÄžÄõbTÉ.1ƒÂÇ èû/ù3·êBÊk1ƒô¡ô¹Žø9L°¡Æfˆ–7Äüð UY9_µ¸áárÍÓ’¥û‰Ò¿~þ-+‘•ª‘y€;Á†|˜È](ñ>eÅõfÄë`ã´*LŸ»Îë <ÒØCñÇmOfbÙȽªŽocñ[¡›¾ùuäZ ùq¯Ã½€©§ŸîsMº¶VØC&õÁü+¾#Ï[ Ø?²|Lsï($rgìÍ¿$í@fºý2í‰UìZñù9)Eûa,4î bƒCp)˜i¥j”Ú^HšlÄŒްE:Úx•ŒƒÒ¿3ðî‹ä^i9ÄLU}·£üü=NõÏuM}eŨ&Šˆ†gý Ñ‘s ëKž°tY=þ “Í Kg Ì»¾+ þŒo5V{K¶âÚœ¶nã4s–®òmèQÀ˜>3Mú§9Æ;ñdıÍõ)Á]'¥@:fÉ2ótN-¢ïý‘ãªÙ„ï$µp¨ÝZÇÜâí]x©'Îp•"Y–ƒÛé‚dK9hÿ­YÎÆPO»ˆˆãÚÇäö€@oó,ùê ¥ü{ö¸Ï6YxÃ"ß(q<Âp†x—Ù€ø )IÜip°bñÚïF6F )qõêˆ(Ñç±Âò qýîÐÍØ'o“ň݉{£ž±ðòÒ€a¸b×Z…%¡¼ô#âÅVÛ[wóÞí ¾ºÀ¨`²n, ¥Ü×Í’ðšå½)}´ËK%øzŽBhªwíýK÷‰Sz?wZ´–aQw]¯šæ+VãðYz £L[ñú„iuåv¼ëôþ¡Êvü»0„¿4’¨;»(¥ —{²k%êl¬øn4×[r"4~¶Ë©6ó¦Àk£Møšî€# C¶à{å¶·W¡¥kFåø§_t¡ˆÛm©HUèЧÑ!ÇÌñ6áíÌ ËŸ ¸`Ü>| -ܰwçÀ¾œ0ˆü©«D…Å™vµŸË?ôö3ú~2†—?;:ŽÏ\HTnp¬˜Õ¯r†øÐÔ™¹~ö¸ËAÚðSå¨hâÑKéw)ײ=Ñ÷¾,Z0N»ê0ï¿.:-áw™C `{ËUPDŠ8î|¶w1½äãŽduÈÉgG-» ­åÂ/£Œøu~œOµ˜íÙðÅ*• f³aºþ…#/eqãcÒ>OŠSÜÐñ™®Îz×3Èó~ܽ]KòlËÿ’„¬Sçøò‡*Y0pIãí|@$ a»ß»2mRÃgÛ…¾/ÛÆ:?3`ë´’ŽýÇ®ÇÜÚù1HœÇË¥I7sCÝß-5èB¹|£ä™á·„ÄŽÔA5¨žvrÕ“ŸPœH´&`Ù%CîVçåŒì™Æp——¢±aÉÖfQ⢮XN”i&·eÀ¢J¤O©ñHÃÖœÂ.Ýæ•!Ø_Aa‚Ï"ΓFþ1ål{}ãoÍ•ô 9rSï-—êF„XšQë3 ÍÄŸL­¯èý‚«}²²eoKm š…Aþ™©g ´:l{Zªs©ä°¥_ÅIƒÇ@$‡JÍHÒwç¥óíŠSoÞĨ¯5_Ò%˜ž‚¸)8Î8Í fsGOùÒꨉ; z¨#Žb+ |dDç½qZ.ü¿…¨/oôDŸrÁ/>‰CñlÃé~Ä~ý+=;ú yÍ3ªíI¦x@¤åbpSzåšÇÆ1¢}B·|·_þ5>Ñĸ¦+è"ôkÛ¥jÆJ„9Lbúñ] ô›7˜âË…w£rÔ×8¦Y£:X±õ#}Mx‘âÞ¤ŽQ¬Œ%¬3~,œÔ¬ƒÛ["înlÜo>¶t»Ær´S­ÙÒY2õøçIŒ†M¸mÚàsøcŠhì­Èú„¼ÖX³%D9¹ Pó¤…ÕÐó@ÓÁ ’ƒ˜êç•Æ¤ Ä„l–.Ð>e†êLª˜Ö8“įî`ó¹ç û(àÛÓ¦M’¾æ°øˆÕŒâÛ¯ª&aé™ÞÀ2C"R¹7s,'¡ü¬Zôæ5ï7vø:Qΰ(ÞÞ~4×^óqQùGd¯Ö»“P««©7F®ƒÞÂäïíСÕýI'ͼZöøÑ+Sø\íÉvzkŠ$XÓë_l³•Æd›cæitú½¾z²Õ >ÙFàk>VÛ–ø>’ñ|ÚÀZ©gqøáÒ©ü„'ˆu¼4Ù Ú’,–|ü5³Åšúñ+{JBM¡p"« ¹‘¼’–§8ÝØG(YÌÃf=K“4±"’CôªÞ}ÉNþëKŒ„ñÏIgûæÁW ¿nÖOu­j:A _iP©Žâö”Â}C÷"ÈåqG”ŒÃÈ0~Íh%“&ý…¥„1w´B?Ù˜µke} B>ÉÔÔ·gø|Þ_¡+zD`ÐLÊzÍàl©V2½ö¥îwnyÙHj½1QZo†~õ¯Pkeùi)Th7Ñ åÉ´€|btùb£"K¥ò©J®G8qž’ì>Ÿ ÕK„~zX΂05ÊÔ]t¹°¦û‡@nÐF:4ÌBñ[jeH½>ë!ë¬o,ëc¨9‰@x­ËG×·Kï5dòK» ïœÖ‚²ÏÑY¹@4…rû~¾Ÿô£É§c$•ûÒ^!œ­¿j'§pŸ D‹OQôQx<ˆ;k‹0ùŒõÆAnÍú›¢Cói…¨ÈT#OYµ( ÜÓ¾9~|ëOÔdhçž¶ˆµ*°s4Î3ŽY5²GjÒç/ò“®¯Ä6ð¿ßdØ%þ„š0`¢¶Ë½†Í‹ÕÂb­ÞÁØõ&³ƒT–L.1|d/ëÓÔÜdšC¬k˜ö¼zl¾û‘¤É~Ϧ³¼[–Ww~‡z ¯áExE¤ô/%>èL"0Îä,2Þ³|¾MX¿¾föˆVaa'râ=Já+&áŹÞÙ¬[•㬣ai¨sÉ™a½)€yWH°^\8S`†+`A‚%ØFdzi(Qâ^ë³L¿·é A|5¾~F @l£ý\ +ØÊy‘s“=S#Ï%¦=ê‹ $PÇÇ0€ôeÑ„«?ˆÅiúD±î-eøÀ¸Ä9T·\ïÍ@‚ó»r×R¯H[„#3t2ªQ÷V.l%_⑤ IÁ2ïÞŒó4+߀‰wû;ŒýLbd6Ó1ή*îƒÈïTf+¿Ô`~´_ÏȇšBt‡àG@2@þpÌðÇãÂdÂ&Òf}$Þ­&Õ‚‹¾8a»ŠVL„õÁ,Œçsòž‰ìLKŒDˆ ß”°Õ"±w…è÷á†c5ǤÎú?c†2Wé—“KûD×3`èϳÞ ð,cQÄiædГ8yÑ™îÓ¬£¶ÂT>ç¬î ¶ÆÄB ¶÷ï¦V~å‡Ä—”æžhÚk@¾À¦y‹Í¾‰ÝsŒb‘§¯Ô=ÖÙe /νŸ'%›”#3 {¤|(´PïãN¬5``ˆìà !a´H‡F(A`’ÔÏxŸ¸×PBšäÊJ2Ym|Tnó¯•ðX’‡í ~Ÿ”æîŠp8=i1 þHˆâ°æ¤'öó-Ð1ĈDV=OÞú»bÛËN÷2àRÓÔ¤t>íp)ø¯£ùw3Áª½©³Ûâ*2·ÿìtÍY v>êHÈ]U_;n SsyíW·&!97á SPì»Å±š¢®~Œ™wª]&äχ @ ‚…n'd»é˜)+ë}ë8jtGÎönrXñ'ô QD.dotžwã7´ì"ëQ4¦ŽDî©à F3¥1„”åp§7…(L³X¬80ÉÈçëdu+¹´:yåhíG«é+¾ë Ý!OŸàAÜ›c<ÓDbkdëœ')‹¸X9$k.U¨›òšQ˶ÐIã˦þð¿ÏÊëÖ­À*èý!‚Œ.ÑÙÂÿíRnÐ&‘¢í'¢Ï5­˜{ßD['y/Ny\èÎ#éE„ض±Þ¯ÈéZÊgÖ‚â´‚ÒMSÊÆüý@áž™¢;ÖèMFÙµ “&DCýØÉ+¾ì·Wy‘§À½QTœwü‹wêtU\°œaz ´.•pûO8‹m {ü1°þ?ºF6-¤ó—È®ÌG}üš…÷u—‡)‚y`ÕYù$•MòTX£ñtµBJà“=ìÍäõœB¦†ð*­»é¢ÜzE,U¾ïB¾‡ ÷lºoqàk 0°™ÿÄ×cºí×Ë ½|bï,èp„sЀ§¦ÖvX¨t.Ó zÐWêlDŸn”øaPýIjWò#ïì/D¬M‡½“è¡p#•‹û†Îß;a#7Ír¥n§ÔzÇ¥.«ø½sW¹ÙcE«•+a Œ?ÑÔzÛËö R²q„‘¼ÎV³ è¬Ä¿Fá…“œÆçë^¯ú¤l¥2x^Ê»—!)$mÖ™G·u¦ÐP+=¨2pcT/sxCz{¦ª`ãÜðGæã—B`¶ãƒ$„%Û±û{y~5ÀIÁ|£QLkXâöcÿf–ø5BªPľímÛí®™!ƒÖ ÌDrihÔv­Â²þõjÂ÷T‹ø.¶ÈyÐZ÷½æÚ÷ d¼ÎåBT,ô‡º6ò †>ïŽF3}í|½>¹hy=¸Ç$X„´ñ X‡úÜTL-›y¢'É-æ9ÃÕΘjöM7³åpáTŠÜ±áŸ´ƒâ=$Zt.×n…U0bk40E0mî*ª N݇ÏìRmp¥6rýª† °]=éºo•Ñ |~ާ%VÛ)Ù^`SÏ]A;‹kGà‹[a¢åRè$@¯ÀÕÒ­>\¼YÛ<È&“Ê®>…1?ù|ó¸'è;é!åÉqŠBò€&`†¾úÞsÉ´Tn7èioû3"L„Ô,æn#š£…2"B¹ô £å€¼æ«Q1ð¥Öƒ &~㪶3ÕÒËžœ|7P¡~ÁÙöimƒa‡M!ÓCæ»à¸î5Ø.´`£dÎÙ7¡|k)i‡Zp†ú°3áu|öò’Ϊ; â ñ\†ñÉ’6æ»ÌyK¯ž\;s†½†ÌÕ“‚ë>ÛñOÉ Fü¼LQ¥ÚË}$÷hw\‡‚Ë[Þ DºVOå %Éð"D m”Âõ•뎷]’hûCÙ¡¢?åÇ/âß[º'Þ@sÆéšº&ך:ìæ–d#s9Yž7I}4æ tO3k0ÄÚ¥ bXÝb>ìßTí^ÓjùÅJLo³/ØvÑ1PC‹ •Š#¼¼h·§–z<öñ£r¬LºŸJ£T1 ]Ü5 ø¨|¦©JÐZ¾Ä‰Ê¥€É 55œ9Hù6<~C iÒ¬¿=Ü^+½pzöjPC”cÝ5[¢N}ŸëúÙñ²ùû2§´ÐHß5uÉè /ð¤Þö˜›ˆx0`þÿ'Øî¯J–Í¢ÿ}rõæäÿM¤‹¸8Àwr|LË{#|pøt2³Ç¶¹°81܇@/Y#ò6y±*ø3^Íž .XعŒÇô#Óõ7õ‘÷€·¸ ßÜzqSt=ù¬»Ë‚wfþ‰ÐÝîf‹ûÓEäo˜\·×·Ë9G¿-d…]Ç {ĵÃ=|XÀ½Ðq*Kï{FÒSRá‘|É›@uu3FÛÉ÷…±OJkÿ…µ3z®1\<—4ÔÎG4®² iv¬‰Bî?ÁÃÁë,Åðñ±­6{*þFÕ“~‘íÏHU¬oõ„¶5®v‹qô[]óÐ0•¤t+E°Fã»(éÐh:žH¼ñVõ;î¨B`Ñ/²ÆØºãzB·¢þ_£Ç€ŸÕU«Q‚Aä,µ¤.[HدénêllµðCòýÒ¡ú4XÓÄ~®CíC•ÙVàÙ©ä·ŸÊùÈ;° @¡f$£,Fl6Ãù+4 H'tâA 6Š˜ùñyƒ’÷>¡™ 6e;­ÕŠpã pë)OF»·ªø£´7'ØU’hê¨þXAxö0ç_-ccg¨é©]PýÍ!¡˜YK8ØÀ¨Vþ3N&`<Ì  ±0hn:Ùåß’’­ÃÏv%üD¹7$䀸DÐ„æ½ ¾C¹Í 9°-m©b½šß5¬œ$³IÍÎUAùe:]ˆÿ^ÇdåÝT}id°;ô@e\9OÒ)—sÍåÏ)y°ÂÔ-gvÉ¥ŸÞÁxU¿Í¡Á'y9¨× îQë ½T\ùë{?mn× i2¾M˜¥ýú41˼Lôëzn7ZÙOme#møÉ¡¼ØìO®ÜNÏgzíuPÿúÚà h?ÑÎ`ˆóÑêùÛröS×.3‚ç6ÃÚž°fwÚ£5úßc€Wa؉0_´ë×— ÀCòà~ƒ(ÚôÎÀ˜”*WÅ€QŽdÖAT]¡()¡`*$ù¨þXBjˆb°-…c"é(?}sT-³ò…0媥>Û€§¤^1”-^¦€Ì:UtÅÂ{P•XM–ç‰écJ |ZÆ-þa|…”õ†Kí¥áŒê?Ìwñ®¢E•!ÆÐ>y¤‚ô‡ r"à31VA2Æä*®lÜ"Õ ú»žˆZœ¹œn ºÒEüÀ`¾ÿW€•»b®{3e‹X¾ÕjcG-MËúhŸ”«k#±,çO.(™f&°qÈyL0ï‡fâÌÍïÅhô {:a㺀¶´¤—¿•‰ÖyáÇh£Ø"kM€‡z…v–'F÷säZ6¦g »°ž4ëe:柕w/ Ù¿Zí#5‡æ€a»î/øø\7B(·ŒAD)-m¢>éš3ÕI!Ñ@,šLŠÌ`öEœKöÿçaö/…i‡å3òmã¹Ä¦M¥PölýVJ§æëbMlŠCµ•ϾÕyVihîìÐR×á$§ÍX^&H #™_›œ®°(2•®ŒÉ+|š±¹ê—!¥AïVˈ÷9õ<(×ÉæG» £9ú ¥=Øç œ}Ä&f!D¸ ÍxHþŽ‚õÿf§û ¡îæÕx¡\‰Ê9H{žs•q˜óSý#å‘X4Ò›³}†+6)%‰+€àûgÅ•rÝ‘þ6³ð§S®Ý8Çqà³×­a)xT]\g˜$c¼“Üs¯˜ê–àgZ„r’º¤N¬ÞZÉéPYe/]ôôjCÕX _/ÈöðRcÛQNº‚ À.˜ž¦Ëe¸K«3é ”Ì€> ]Â)Ÿð %ºB=˜²¸Eè¾bqð¸ïz¬º~ #e >2“$òšù§g«Äí9…t´׆§wëIAÓÌ/>Ö'ùÒò7qS>é»R–ÉF¢JË;Â]³þönw{å}ª†&  H)ñNËp`W@™&4, qpðÀ*œÊ ÜFYªð/­)¦U2 /#1O26à­QÈ•!ÍçŽiO‰1¦‚LA!k\YxµcìâÁ:âaÀ`Åx_¸»Ï“q;@¥C{@1†K6ö0|ˆùǾ¸áÆhDv^wáø{|Vé))Å0†¡dÁä7I‡áEÔ Ã©<±äòîŠÁÑñ¬êO°¿žv, ]й¬(h¼Þzh²ãøÛߨìM,jËM>OÎNŒ(Øz?Э§%æø9Îr”­v/z?Lç¡Ù胱R{ŒbeU^{ìþ4|¾(–ÌíXýaGAjE5Ò¦Ìc†ÓþaUKµ¦ÇÓËÆŽÅ¯³u|8<6„ïÚ<"Ã,ú1'b0⣀A0arßËu³4¨ÆÑr+ô—èl°P¾ëxIÞˆ&¾ß&ñqÅôr’2.t îÂú<”š«WÒcTcõý§Š|]€tc÷5¬˜||| uI8a¶¦P±§ÿø’ò…/ÆÕ¥z³¿–dL t”XOˆ4‘ISr’7#)ye”â¸hòÇù‡BÒÈ/ªð…ÏÒ¸¬á½»%V_7ÈO)ù ÁPß²JcP#/OqEÇ™ £öýÂð‹â¦‚ϼÁ,ºØ‰d ØsOhˆË=%ÍÐÊý“æ6½Ò½JL µô¸µ³”H'¹5 麾&ÜmÓ¼K¡p7IO$åˆ>)kÍžž÷ɘóE¨5 Ý •ÐÞkÕ'Ë„ò61n›Ó[´Œò²«ÍSw{Ó¶ãñ §Q1ºÃ±7aˆº~›4+©˜(“ƒs‡~†7ê'×ïËKär#íŽE3Á½Ïé8¢ZoKžbMàýÊSÒü{­õŠ‘;Ásëµ/Ž8ªN¤ ]ªÚ/Ü&S ªUðË:[²ú²sC£FÇß­ÖävܶÇÓCaóQ4Kv‘XûÄB$mjÑ{¶@yA—ýãJ¢Ó¨/ò &;%ë•“£á 6½ÐBë6®wž©æ\ (r›ë+±ÖÊDÕ|•g³—çÌ„’ñ¤éïˆ:8ͽU*]™J¶DæðÛéP$ þDGß ÖYµ8¨0mä/æ Që}Ï΄’;rÊ»ž{k Uq#khyµeQ_°BÓð`!™0º÷§`çJYƒ –ÃÔtJÜ,fÒ“)}ð3Ò¨Þ#3ƒÌ:±O²î™o‚Ã[dÚĤ_‰|[¦JÎ( 8)¥èðædE!‹S}¨"ÖÙ t¶Ñ1ÎÕžOcðqÞ%\D¦ý) ýw§ÁæÝ9¶mdžÌ~¥©¯Tçã¢&anˆ:u­K] ó ½¸;ÖsâèêoPÙƒøÕ¯Ô5ýwóß¼W2ØÖqL º]±ÄJ¿gúçM=ššÞêo †` q¯è<#¯<¤óD úôëz#•KaRS¸b|‘j†”÷–èlüjÊÄcŽÆF]ß§>wÒn 0O£¥ G5þ°ÔsÍ…aŽ ¬ŸöÆœ"ï_+ƒÕtRw÷¤Æ´[›}çGÌ=¸­Œè¬a³q>¸øïíôoÞm·]˜»´[‘à‚¾Ý3AJ¤âôPP¥ºQ h÷lZ[‡Êub‘³¦6m*Zw9ÇõÑÛyW!‡†ôþpîמç-Y-}² í¹Y‹Ð±–ßr8®Çƒ!yõá@N­.¥'’Ý;1«î\ŸøŽæ†î)܇‚ÓÖXiFÇÇÎ,g©s-gÛ…†-K&«Udà ®w ¡ªbâ Rî̦Óó¿‹ð5Ü…¥sI„1Q€žCcëñä~®M]ˆõÞHýès™{úbµúSÂ0쑃 éPmçåÔk’¾2-R2—4~%ÓðÀgØ'c+ýVÅ5[FþƒÔtYÇÞ®–U‹÷puÒׯgwÔð-C½&¯ÄžZ P§0`À@ü Оsþx¨%`´[ûrœß¡_‰Ô‘0o4[•‹°2xÙÚ.§li7ð+õ^0œÁwKAðà ,—txòÅÑ1¦2Zö€Ñ¿RøåNiK™aÿº»6N¬W'yЄ4­EmL¼">ÙzXÄ¿‡Þm%#DÁn‹‹ð‰b !g‚‘8¢½Ý^ý°Õ ·Nh+ƒ×_Š|Ò5f¬Rõs_GlÆ—‚UPr”%öžÁ™4úšîðÝF½Ôš­LºÖf‘;_²Ú—š: €gd{~!z(K²¶’á8cT„ïefúZÙ¥O"qý\ïÇS40¬>mw*­Ÿ-'ªÐ`Tœ ùÎ(ÜŒ÷ú-œ ¥ÙÕ ’x£p°% ýpŒ7˜%ë#s¬™N$°*4¨¼‘øé´(}Í­½Á3Ð?\ú]šD¾y•4à°v=Æë~ þTæc2¯“¹¸æ©oNøz Hƒ¹C•¯[y½?;…!ɥؑJ„‘)‰µ9ýeèÁ«?ŒÅ†£iˆóÒI¥ä >#.- endstream endobj 814 0 obj << /Length1 2303 /Length2 16611 /Length3 0 /Length 17958 /Filter /FlateDecode >> stream xÚŒ÷PœÛÖŠâ!¸Ó¸»»»»;Mpww$¸»ww—àîÜÝpÙûHöùß«º·ºª»Çô1לëë&#RT¡2µ3ŠÛÙ:Ó1Ñ3rDä„5™˜ŒŒ,ôŒŒÌpddªÎÖÀÿÈáÈÔŽNv¶Üÿ°q9ÈDœ? åìlÒ.Ö&;77##€™‘‘ë?†vŽÜQ#W S€=@ÚÎèG&bgïáhñÅÜù#Ͼ(M¨L\\´»„l€Ž&F¶9#gs ÍGF#k€Š‰ÐÙãBPòš;;Ûs30¸¹¹ÑÙ8ÑÛ9~á§¢¸Y8›”N@GW )à/Êy#à¿©ÑÑTÍ-œþ¥P±3sv3r>Ö&@[§[S #à#;@EJ `´ý—±ì¿ hÿn€‰žé¿áþíýW Û¿LLìlìl=,l¿Ì,¬qYzgwgZ€‘­é_†FÖNvþF®FÖFÆ—nR}0ü7?'G {g'z' ë¿82üæ£Íb¶¦"v66@[g'¸¿êµpš|ô݃á߇kekçfëõdfakjö S{5[  ”è¿m>Dpd_€Î6FFFv.Ðt71gø+ª‡=ðo%Ó_â>^övö³@ 3àÇœ—“‘+àìèôñú§âÀÔÂÄ` üba ÷'ú‡hö/üqþŽîÆñc0þõúï7½ 3µ³µöøcþ÷3ˆ©¨)©‹Òü›ò•ÂÂvî/:63€‰‰… ÀÁÆðùß8ÿíÀØÿ-U4²øwuŒ"JÙšÙ¸þEâ£{ÿ!âúïÉ ü÷ÚPþ7ƒ¼ÝÇ<”Æ_—‘ÑäãéÿóüíòÿoöÿŠòÿ:þÿ·"qkë¿õ”ÿ2øÿÑÙXX{üÛâcž]œ?vCÎîcClÿ¯©ð_ -lgmúuRÎF"dûÅú¿m´p·pš*Z8›˜ÿkˆþs Á­-lŠvN]8:&FÆÿ£ûØ9«KÅéã¬þV?VêSŠÙšØ™þµ{Ìlì#GG#8Æcfcx1},©)ÐýïÙ0ÐÛÚ9¸>ÈùÌìáþ:Qv6ƒÐ_¢!vƒðÄ`ùƒ8 ¢×Çþq0Äÿ &ƒÄÄ `üƒX RÐG>Ù?è#ŸÜô‘AῈó#ƒâôSùúˆ©ò±Tÿ ~jÐG>õ?è#ŸÆôÁOó¿ˆë#Ÿöôaiô}XÿAušü±~dÿ¸mþXÿuª ¦ÿ€Ýþ~ÿê?–6fmdóŸ¾fà_ÈâO–¿ ë?bþ¥·sqü‡ÿ‡É—À"Íÿ”üÑ"s{óÀ‹™Å?àG•–ÿ€í°úüè‡õ?àGCþQ;Óý?‘Ù>\m?&ûú~Øý)æÃÙîÔdìÿ¨? ±ÿ¸5ìþÑP¦6ÿàÊôQºÓŸ|! ë?¸±}˜;}\¹>bþiÿÇÅàlîüG;?8»ÙýÃჃË?à}×Ànÿ8«ï$cþïñøÁÎó»Hž@Ç¥úŸ57qqtüxþ}ÜÿÁ?o@w  Üò‚ O°empûcµ®ÝÞß,ÙžF ײc‡Ë3t"UUFà†ã½Pâp/òÚŽåà á›×IK=tXk¼RÛ‹÷«A¬òô^ÜÒÆà䡺|X<:UÁ}ï7oõ+ðÐ.i²N$Å<ÔG·~ ÷ºÒձЅ=¥ý*vø×ÒºïjßtŠæÈr3籈¡œéða¨Q.Ý?ÍÝÝÏ¢dO¾JÇÒÀùœ~g)ðÒÞdŽzš÷üU®ÊìÔMŠ­…~‡26Mî%|˜$¹èU\-Yh†¯¿ÐÄßñÉȵ†¨k™·ttrkëÈ @¤ôÓÎth´‰Ò6™ðð‘µJv'JNGÑÌ“A>œ“RçÁ†gdÅ\†cÀ •ó™"sXj_œ5Að¥TçaØaÒ"ûvÞà—ï E}Ü»Ÿ`ì³q®³N—‘;âY'Çã•Ï䤄-L–έªÖ¿êÞ0‰Ñ“9Q6”áY–ÆÐ`%Ê»?(nÉ÷i0˱š é.O¤÷>ù¬“ }Þý'A°ÍEÕ=—à%ÓRàtTš%·t-ĨÌK ³J^µNÂÉ@¦°1ŠÀX¹h ]p-GU±‘Ѥð< œæ°/·EŠøÜõÓ%3_áL«„Mã¼§¥J§ÎC$õݾÊ}ª,›’ˆŠ^0e–±hÄçw‡ÓMÝtIÓc°/VÎáó¦¨bË Ÿ7ð;bQb—ËþDÏJBØ"IçoÒ¶ì¹7Ïn IQûíVõ~µ÷ZO³Û7µ­»¥!O/R@©>£{!¿¿—ÓÑÛÌò rNHàÚÚÙ©§D.T±é¡¾3ÊÃLÅ£xk¡ËxóóxŸ!— ¾}Ôà½âöPLµ¼‹ã•,Ÿ‹yIÔ|àÌèÄrnkâ\¤~‘VS3!dw÷Ü.]ñ„§õø*KùïýŽdfçž7Øü0t!ÒÂÖ8}Â4º‰{k)F¾+Vr)eZ ¯6oûR›Ìê\Zè,çëg‰Ž\FPªn?G­òøîÅ*´a“

ÖnÝ¡çÍŠÎqßÍß&9(‹r†°Å›á¨Df\üŠÇU>0â?Jî+ø!—öSPS ÷`XãÛñ9=`j04ÒXgOØVŸ±xùi%}+õˆ@Õø«|?£¬ûRApa&IdÓ¡ÓLÎ…A%3?¶ÇؤYì?Md28Ö$–œÞðk—­ LFsn+jƒÚÆ@‘ØEo§ÓŠ¿²·âÆ&Á :Ÿ lN=•ÑIñg_ÁuÄrX½PCúí=•4žŽè`ÛŠ ¤ ÷âmÌãKf×íÍþ:éME0ô™ "Œ.xjyø§ä¥{«´BÓ°ntÄ4¬u¤ëü3-?RøH*‚2Ô`íbáUÎÃtÒ ?áñ'òÃòo´M£/KÌÃ’bj#£ûùÝåÏJòÖíw¢À 3[$dý— Ìùo²gí¾ßΞägâtƒ¬Hó\JÓèÚÀMâIc¿°côZa£F-ØpCÉ# Egzt:.‡æìn^BŸLxùÖ+]}ÒÇ>)‚ˆlÀÌPGx; -&ŸšÉ ÒÜV0T|/ŠW±}ú1°ãKòÝÏà3u¨~Vƒ®Å%ú“ô¸EƈÃhŠ4@¦`Ö‘óÕƒZå Éç>ÜBBÝͨ s‹Ô¦6Ô•ÙS[ W_vþ€QþXÙ!ížh•šcØEV¡}‚ÏØoÜ÷üÕà—4ì›H ”/ÛU$¼*‚§SQý™‹¬a’Ü’i'1G–Lç,<øùÃAÛõnè/N@¤×õuÌïWC*‚^zÑP<<–ÜåýDÒDl´üCØÔv-‹_mZÒÌ/§¾LQ̶ÍYå÷ðø‚^UÄFÿ1“è2æÓØ ²€WQ]¹úÏ*\’K—JßÛç3Ín%Šô_uÙØÂIv–]ÑuB´&ë©Ð0dvU ôñê}m[R+äp4_h9Éó9ŒMI'ÿJ„×wfÐ@ Xò˜ìòëêÇ*‚¹)gmV’ñ¢Zæ Ñm7åo³Ã¯h§Û/'âXÓ? *ÆÉ¾G{—ß“ØC³wÉ|G’%TÔÝð4F*ÌÖ5™yðy8£"Ô]’1S`þô«2`{@)?W¯SEW|ïpôËþví‚ \ÖâñMÕʃ¿•b³Vòlak:.ê©ëÅ¥®Û…ͺÞôn—µá¨Ù³ÄDÖ),ãQUJ‡²Üuç5dÿ›€F¸üc¤:u+bµ<¤ÅŹ¬Ù™øC‘|>ÈX‚òĘÑ8QÎâ¶ð±³Þg nf:dùz‚2Cª#ë“à ¹çâ$ŒyôEq7¿¡ E”Þµ_½v·â8ýhÔâbc¡c•ÀbŒQðð§ Ùx :pܸIôÏ¥‘k,>ª Øi+¹Ñ¶Ý$Cúü`Ñ39 9téÍþëþkânr ª1U¢NÒ)£J¸­õÏ=A^а/ªëM·Ì•êØ±•òN3Q/ןü:É„ƒVÌ¿]¯’â-ÒnÝðgï‡áÜØÉ$¯KfNV!Í}Ê4—1O#«sPH×P6^´áÿLŸ¾®0aR”ú³õ@o£4j9,Nf™]¬XÇtÞæiÌ<\Y£á¿.Gc#ÓÜ2øÓŒ–xÅ7¿¿Šçå>‰#£§‚oÔŽî@™Ì?bÓ6 OZ¸OÐvô]ˆñ¨×¼MYœ«:[uÁ+†2<å’t#$Æ{ôÖ¼ çáý.Zîݲûº8a ÷”,F S=ø}å«ÄökS ”€¡ ÷æ ·4Ð^yp¬qøÓ£ß6WzÈ·œÑ_¼Z:¶CÉ·?×Á¢N`Ðf7;·‚8IŸ»Hˆ0S|(óVøðøWfëfÁ¹IÑß²Gá+QJëÝpŸŠî&IåÛ‚WxóÞŠß¿[jB¶i:¿É9â,‹UÕŸfÎ˾R›aѤª …ÇNŽ€!Ð ° tï¸s$]±“àv½ÝDð}Ý!B}yƒNv)ÀŒ4Îkfˆßèª[#H*>è–èoíÌ“Þ;òuR Ä0â­‘s±‡hÍÕô˜ãï²úkqì×/ÈÙë‘äyr>K«ÅC,Ù¢VCæ†ßu³]Lù7®x,Z„p :ÏÃÑáìÄ ¦SM¬îäÓç" m óž]Ñ穘ÓWSãvIIÎÙŸ¦½~_À¼–lW6ꊻީjàÃwù[ŸÃ‘¹Cê|©ŸC> ±d÷-@ŸC_#ދӷ²©½ðøÔºF†÷›jŠÌ¶Qc^À¿ò®ê ˆÅï¸k2:0iµÁ³jUMŽ9zœ“0ŒÈ5ˆ¯´æœry¬“Çx°ž‡\Ü;cu[–¿m]ïÒo£Hùãr`ŒýݯÛv Ú Geûšû³á=ÊBKリo'Ù>M+ 2x™(‰\ù”™Žtà -Þû.í8ÖU³¶½eOÇܵ}3SÌ·k:óï’›¥Ñ§ MA:g7`XÕð2_¾fŸN;³<¨Sñ™ù}&æ ?í1߸±µ`‰ [¼^çë™.ëå ¤ ¢ t˶‚:hç:-— 3‚pMþ“‹jæqS#!ù95$ð‡¼>y‘‹”÷ÝS0ÍûcI1<7ÈåSuš2oÏÆõv#ñ7=ø‰ïDê# yÅKèrƒ*lˆ,®þv¾mÇ ¼Œ/ïÚ¨{ʶ‹‡‘<É•’ &ç”íi’ŽAa`oEëo·Ðp59Óƒ³¥ÎÔßëfõáÐS nÜ¿~‘Œ"‘ëʵò¤S7±ÇÞ½nëËõÎx¼H˜¶ÜÉâ±Õ’ȬÛoÆÒ¦íØÚ÷`ÈújˆÒx;˜jH°WÖz0A—¡Ak²BÊHÔ’ôŸsL°ÌÓ9b #DzÛ"N%Iß,£àB%n¢óÐû‚F‹ÊÌƒŽ®ÙjNñ任ߴŸ`½÷j0Ø$öŽt â&‹m¶39_` ‰`ºêÁ±DÊÍ_Òè³?,M>˜g tÕ«øImʪ6b>3{ҙàB—ÎUÑ×A|Õ3®tuäéØb ¿­ÙnõŒŽÁm=RØÍhh±AnŸ:aÉv ¤QÀg†/¾ýœºxKu’®‡öÉ–ú‰JÖØ: MN_ǽÙ<.¤Ïh£‚*¿ß‡aUzØíÉz‡X8¼Òž2¡QÅÕy?ñz@_]ȦôÐh¬òB¯ª…ŽNO>dmá¢1QƒËþKŸžlù[yýHÁ´ÿ±a¾~6‡E¦H¸}˜D€ïÓ¹ ÓñèÖì%¹²718OÏû¾÷4áU‘ a¿Z0´v©|@ÑŒ'¶£(zÌ Ùíò»¶:˜ÞZdA`.!©fY’\¤Y¨.CV\ur”_ž‹Yk†–y„_°ÖÙE´jѦF*™EEzÄa~94›“éGwˆv¬«íš‡§ž`/²ËSìPdûÚy|d¸†vt¶|_C–&~û3£“ ËS;Õ‰ŸÇ©äKz›]0Ò:C¿«éú þì"'ç´ØÕçJoäÿì6 ¤É¥+²nêÎ5ÍHwE½àß.Ža¶ß"Ð!ÆÄ¸Á²œÛZ…ßV‰·+7Êœy‹àÊ}&fjš_ËN7”Ê %æâMR¸—vwVœÍ"y@Žûd=êá;¬GŸ)×Å”}^XÈê%] Þ2½ý˜íö™Z‚¿ ¼·Ö]BöGcH ³&ÜæmÇNÚzô£ËÝãæ“dcR„©–Ü)O­Ý–ÅÉK¶Q6ßj<0‘,³hò釳PGFß Aô±û÷šŸÇ|aŽk1êÂ@T;˜úÑRÐü0ÿ½æf2Úá Edú­ œõ{R[-à÷¹g ›éßD¹J‘Âs)Î ÛÀÀA¾ó²÷‚sä7–CÔ ©ë-*Á,”(¹‘^V“ÕΧ™. ÅѤd$DÓüÊèy|V:ü.<´F¬‚«È$öð|”JúUʾSñ³Q{¬ikBÑЯ0YHWWU‰Úª!صéé½ ‡8ùïëo­ù)AôQ«£Ïž5عH}‹F±bâ7TÛÅôÞÏÌ7\¤êŸÛÁ$/Õ}ò8­JòŒzX)mBÈ-ñæÊ¸8o9G,Ì0_$ÒŸG8 ?~»øüDÞ€•»‰šmˆÓÔüù‹ÿèct–W–8÷l”̧ѥâ³{ŸO“ß幇qGçáw¢ûBHâŽq72™(“»¥AüS•eu¤¯Þ¹¨Ü—aøõqÝÖRÁŸb'9ºÍ*e+Ìh%e‹¹LJx.¢ KjÐja¤ä†ÔNü®¸öQ Ñ»V5øç¾°9KØ û7R!ÃØdòÅÈš}2}»§Ž•‹ îx%8V9…\¦P¨€OU¨Ø ë1È•¶Êá/è QJ=xR¨ÉL’†øÀ‡í­ÄXìT™é;Žù^³"ç×/©¥•†å?åSÙ{cÆ”–$HcŒE’s‹aÞãìWø\·-H9Ž,œËULáÕ=lÛàaæñ=ƒ˜Ù!D²ù)i “o•ººÞ¡ nËã­ÙžébžVˆJ±-ÜÝT¼Øûe‹öÀ%cåÆ4ÊϦ‰ÏRîœ=Ìc/󪄀RõÓçëð­o'Ž6y°'æ(“¬¾bËßñ6VØ*Ù‹ubø+êf¾• w«SÊ`EÁøo€*-ÅÃLLê:§½dehhΪfâQ7φºÁT²Aké•r ,†¥=›Ìç=WVØ×,4 ¤£w©©U°Æd Q%î@q»`ëÐ÷&{fCvP¿–€(%Í':$‹¦GŨî‰èÖdZs=2Ô;xjˆÂR3é}JGp¦6ýÚ~ÿÜ ª2áàÒ.^¦„Ò®c£uÍ•H¨ôš)\™o¥Ð]»ìÈVÍya•*ƒ~+¡·,a“âQëÎ.„AŸ?Q‹àËá¶›À“=i툥"VÄx% {XÆ R,dQ¯ç@Œ °|’ NUÍSˆaõ¹k3@fÁzTÀ²jILŸ¯ÈÍx°È ë©KnMÍC ÔŸž„_î¸UAÏÞîédØ™³ÿáÍkž%Ú—hIÌh$]?˜ø#Ëx2¶U&,S>az›±Ú“ _8+ís¨€n:œëÄÔ62<ÂëllŠ>Ë1öÿ‹#?³ØþI2z¥2PH5òH=ìÖÏÄ]®Ùä¾ê«…óeg>°Õ‘P4¶6ƒ«0¦Z¹%Äpco€…b±XŸU"ñx¥(qªüŠý屚ÂoßpÉŠ™ cƒJn:=êúV)ª‰tåüH,ô¼Â1J \9yçÝjÑÈl.W€açŽ:ÆðI&WD¹W“MêaÿZèÛÁUòCÿRG”‹±•ÓŽ¢º’ õKsœ‚—ÏÏŸ ØÜèi›Ì»¹ŸzÒG˜x«ß NE+FzªA.Üòˆ a^b7Ï­ä,ÆçmƒÀp{s¡ËTp®Ûˆ]ä$вšÇŒhšç´…[BÉBg1¦ý^™Ûî„ÞCöÐLl^7…·ÒŽäI7(÷g'&{«´V2¨Ž‡ÅÙ®bçöï·Uy§ËÙ¡¶´Nm¡I¾pªÏQlÁA’ ñ+çkàØAOCÜk˼]‚LP°.8ËåÁ¢`mÏ#d`A&€¢&%<¢U–Žäíc€u%¸¶¼‹ç¹dÇPkP7W+©W^Ó+%H+÷~!¹¢å¤Šü'~^w tˆÊYcšè gB¯¶G42ÑÎ+_í™ß{”r;ðaáì1äTFæýÙ'˳’ÀûƢ꠶ ‘Òäðã1Ö_é7XóBÒ’³%'HÍqËæÊÚØK>¡+_£K˜)8)<žqŠ>+EÒ‹ï&âJްAD"+s²ße5é´xç´LYŽ­LÒ`×â4JrÒx–~#¼~öÝ¿BG£ç×GæI±’]m_s`ÞeÉ!ÙGck´&)ìk9ˆÞÃq­á(dÔŸ² E¬4l½ÜâŸìú£=z²ê Ë-í .|òå|á Obm—¥AäïÆ(Ó+ÓØ6—Õ0¥Ï=U]]íM¢õ¡f›+dŽÌy›1buêqç|YÜ)Oâg0¹#Êï7âm{öj <4‚“Œ™j6À¹F‡ Eô‰gà%y·’¹ô+®WŠ#Û?GL“Ot÷uQe°Ùðõò•ÒIb bUÿ3êÕ1éYb}šòù3ÅìÍZx$Y™Û¥Îõ; †¸•o,Q<ø‘%zzÏPÌ8%äÌBPÏ‹„„-hm1IÑP–(‡I “®¨uFÛ#SóC§è€ž¬‚‰Å«š>O¢[‹bAÁƒÆe©D ˆ„~0üÎdü•Y}ÛU4H dÒÚD?Á×T]ï¸<ð½ï¾H?4D(Û?­øhÆC—,„èØ2ñÇüΠΨMð˜ñÀàaKÂÄÓ¨ÏóAÊLméÀLÐyM(`”Ñ#Ï\è¡g=*Í!Õ›¸5Á:de6EImJC˜ôHÏõk®½†0>÷^&ïÛ˜;;FëÆ‚¦³uBa¹XÏ«-MU›S„./:1Œ,ņ™»Ê5r;ƒ+q”‡l5hfùîÒÝ×öæ¬õ™Œå9?“âb*0“÷< )¬'Dìbyoš¢EÛ¦ô0 ÚÜ;d,ïÃ)¯mÞ³A¡oL© °…îñ™¶íN iãÈ%µþ"ÊÏS—÷Ïx°EÔ‘îMµ*O¼s>àBr@e—þÜ|§sŒ@™poÔÙ uË4{œú‹uƒ> ðØÃ!;r|Nå=ˆ»C¬Þt ÌŠí6Ÿ0ù- W×:ò1à¾OáÊ ><&Ã_ t¹›W^wýЗ°†l^CýeŽ‚ǘ+{£{ÍÂy¡SšZ#-Fs¬K9UD#,…®:"áHV§(Ž â»¢Po¨6Ã3"ÆØðÿº´çŽäÛòò’þ­Tœ×ûî.Ùgn £Â(ÛUÿ«—š¬¬îEWfHñ>$¸˜ õÅëòaUiô»8—ä1¯NΠk/é;)ÛNׯJCd÷¯;¥ãßYótOø"ÉQ¯íMãÛƒéü áÒq·++Í·÷±ÆŸ%ˆ_Ý1Æ*KåuÉ-0ïÇvVˆ ʆÒ×—Ka;è¢÷ìW¦w±}íâÚšv‰eµ©Å J%)oh²ÛþjñÝBÔÍ‚@… @«/E(#EmQŽ(TÕ=‘°äkP@‰Ìz5ƒ~›TtOÊ—L¯þ’ŒÌØËíÁ5Ž Peò¼lßw>_y¦ùajîºQÿq³L6–ût;lÓõ¥DSîeÒ*ÇPEX•J®§ÚÃ`)&)ßé=gµ^o3D!ØU"wˆ™*æ"Pƒ GmÂd8½ˆ¿`aeH«¹[¨ê¿î®Å•ýÜÕ/Ö ~ƒûR›WU‹å× R6Èù&%PDÜÃÊÂøÜù5ÔCÇuœäkÙ …›VgUÚÞCd£Kf9‰Ù4"³V:qbœô&ìþ€üSè¯Ü~U}Mî¯êåQˆ«ê ÆÕêw$D ~SØtT«à6t_{×+cOÍN²^«ø«Ñ1[Ÿ‘@[ÄzŽû%ð8äI.ÒJ›VoH‡aéÁÆÑ3ô]aO¹Ö m È GˆUôß™RñCÞ›Œß"WHãõåô^Z=ºþöK~ü~/1m«qso¶o±Ž8YcT( ÙY°Ù>¨ÆLò²ht—¸ã®Ÿp­6p…¬Þo!L€åº;”[ ÌÇ:Üþø‘{©UŽÞ +57Yí{Ó'R²+Þ‡%Æ™s—:ÖØŠâ¡¦?:ÃÑ0L6˜[c+`qÞBÙ~R®× ·[—¸Û~!ØÈ VK}ÒK«Šoär´ú€oµS»ó^ꋯºù“°î)ÈBz)Çf21'°.cGÁS –t‹hˆ~ÿ> `4÷T‚´WRùÆß8¨]òrÎ᩾Ÿ–Ÿ›:–zŒL ë^\1Á&†sÓXUNwžøY:àɸš)ÏÃ|€¤q—c‰Ygp2è]ó½h¯«¨ºðK Z"Ùßr c@÷Y+Θ@HæÏºÁ(®ïLAÑ ·nÚû‚Å_Qõy‚+ÆÏ„$ó9:ý$Çu›ÁA7uNº£wüÍa¼ÆSÔWãO;I¢£Lý+ј2t¼I*tÅ´7oó.ЉgÚ…KTÚ”×93‹Ëzôó¯‰ äØ3Q51vfXà%zØ!ÂÅŠ¢ütÕÌÓÖ7ø*©¾-⤑À{Á{.·ŸmdŸm}bŸJÆQØ$ ëuâÙX»ëЧŽt²¶©@û@Ö5*»¢š $aýI–ìq{TðRÆÇXj ©× ‚“ªj– ͹¯Ì‡ù†FAc':YÇpÝ!O€w†Ù¹öhôû ]ëq˜Ô%\Â^×`}/ò^5ÙÉë©|:០¦ kE‘Ô\XY7XÏèhšÒûæê}†?!ÓaçÀêÆDvOs„FüÆúõ -7µ,ûô \ÊŒmnÕEk:wÐA Ù\[ý>¼Š,[‰¸Ã§wtçÉàEŒ®A@€â]¯ºzK3ðWž ‘Þû" >Ñ}uù®%)±¶U¾^àèQ±§=2M“Þ?kx*@ö*Tjšë G ÉG=¿p]úÝDùõ *?¶ßEÛóïá;v’:Êô.w’û«æ þÍ 5áHT˜æaÔ‘ä° ÑEwrçBúx :S˨¿¬@Ô‘ðÂsñF ›±—r)žŒKÁ| ­¾ #¥ç ª°¬‚9 ²Ù¡÷œ ^à9—`we»¶ñö¯«¯/8¤Q@Ó¼ë©3‡ÔÃôYŸnn+/hnW¦wow$%A©ìµ„¡IWé¢0Æ©I‰æNs‚ Ñøà¢ÅŒmÓµì "·-Ã4ë§²Â<òç ,²ÀäÕüv$dÆ-yëYµ QhÂT¿ä®3,¤Ea÷3zï™ú×|AÉœ @dÓõ#Ô/#¼ÔÂ-gí*‘äõbÞ6^Ö—Óÿ~DÙryö0mZ¾Å9PDáü9C7ŸŸ•Í)yå=*¼xTÖSqSE…φ@®7 êÜËÊØÄß‚ZŽÀi—þ6shOìuÛû¾€R>¤C<•…xϵ?›1Ƙъ@²`hÒtïNqØ€iwãÚ`&¾³æaÁkª(iEئÐíL…rf°¤¨| «K&%Ùp4á¬Ä]¥­…A¸7@ûÜø„J]¨;_ÙKNÃãœí ›g¹IºÇ_üršc_Í‹çý²gr»Poûü(Éýzôa)wg€šjpv¢ÃyJ†Ì)oý·[Væ±qY¯$yä˜ëMhs´Ô\º^_A ï÷wCvÊ£U_^uïGPIþË\?*ÀãKqb,Cp`<"à¸Oˆÿ÷AZB=‰¥å9lP}l,Œf´æ"ÕfUU¯­8“æÖ¢‡»Jfæñû[ŸÛæVqÉU¥á×´Of¸²jW BoE™ŒºµÐOTA÷î¹Ùî<ò.iñNwŸ˜â©ìÖ¨üŒèÈS–aªM§ô…†µ6ôÅãa¸+¡ò¶Å;HËé~¯ï˜°uÌD•ÅõÈï6|m«WyJûU-.-!³øù1ùï=¢ÊßðfóúQÂsq„ÔºTmîè¤DÐ:‡†š¢…Ͱ!öâ@vu‹¨ŸÐõ›b‹ë¦7ÁÍg4-]æW“”.Ž=mÊ¡=ñ¶²e»•GwÀжöʂΠûÃLë¡D Ufòm‡­uA)ú©Hµõíì¯Ïô¨hSÐÞâ“‚íˆÌ”nG¹`zZƒy]µö×ç ivk…û\åLa0ÞÕÙï±+"à¶.¬ïìËFD6îš:—G¾Õ_-îœú•0¼DßÃË ÕÖkW™Ø|Õeèeć§aá £«¤’Ýûv[ûJô£)ýâj"v¢¿Þõƒ*Ë ·¥fPr5â9T3›À¾«Á³`mòPZË]Û Œ‰ø'žw’Ö¨+Yv‡BW»Ebó¥[p±½ã°&89Zøj]‚ncèB³(}:UoÖL@;\^r@R“ùŠ ¯Ä“6Ûóã³ÈØšx>Ý‚ KË*§zÑJ€.=œRzí«ÅÀ‰Ñ.»Bú—²#Žè©JP>Žþ7é¹YØp”ðø“¯áºHô6ãIÒ».öúa<ß°$QÒo„Æâð¬j[,>•N£ò`]†w›áÌ´uüØõÛ~äׄ o0Í»˜~Ü8U)HŽëR(›[DçpK箌d8•‰Ýð‹©Ëø„$¼2zRܨÐN6¦AÙ”«!®—™^ú“µwœr„ÙÌ}$"‹‚lüÏCCš2Üûð§{Né`p&§^DN « Nq¶X0jû>0õ? ÝrŸYߎ®Â z¤¹¸BWÜÌý›šqìõ|{WéñM¿ž—!Ͻ¾â«ªÊé(|«0¡åÊy^Ž%¥XKEò–Õ—à€AoVXÖ„Ïo$³2#uõM·N“ýÞÅ”çsäÖOqª’bó»…G þhâMápcïFýï¡•K±hþ‹YVÕÞ!ȯç²_ y*{´ü²p£H(LŒ1ݤØî• ‘ù+Ÿ–IôèÄòSF@™Ô)lÍp¶¬·ŠÄ/”!í—|¸\Q9Tu’nÄû1²¬/ךBg’ê-Ðk §ò}!ý¢e5ÌRÆ%æ†Å­:ˆ9àN‚lÖéFºS:WcÌl«ONAyt%(¢¥œª¹_ƒÀ0¿U”VUE:­=WÏÔŸ¹w¾áéKHód”opU]•+#]å·ÛåÑ¢y»ó׊•L½p”t{ˆ¼1%Ó€bñ¥fq“ÄŸ5Máb&ƒT¶¤T4mêÍUõ.Ò<Ÿ5Ãè3î÷ Þ]©„¢&”Œ=Óˆc«®-Þü5»ÿ(OoNcJŒNfÊî,›:?ðŽt¶kA…‹ SM² ¹"Ójé+†îчQ#s€v|¦åª–À¦¾´˜­r3W`¨mm¥á»Æ'xî×ì}w5yæ¨`õ‰Iã`Í‚¬Ãµ×‘%SGÎäk’\Œj^6½ò± H¢X~e<ÿk¡žªEèaQSD6E`»ðIKàf«4nÆ}Wm¼¡*ã1XŽœº|½mð¯Ñ–Ü©8>Nì>rFÉ¥Œ££Q|_6èWœˆ‘ôW.Ÿoº¯âü[˜)[g)5À³Gv;FYM„TfÙ$½f`Vk©2^WBÉ~¸Ê_ô¯çîh,Fä—óßq®mÒs¨X¹Ùë’¡Ð^å›ô›[nü¯­S«Š+Ëô¨mºþÄ¡ª[ï uDçÑÝRè“6ÏY@+‚Ddì¶µ¢It-Ô`OË´^‡ÖÁHNTɨõ*ÈM)H œlUl™v¯/xÍ)„ËšLñ›Ø£TàÞ,¦«ç!“§íÿ)Q [[^ímCÍS‚ÿZ,¹ ÙòsyÒ7!½EEžØ"Âx :ùt…WŒXfÛ[yi»ZãiçØOßGÚý8ÙQ‚è’«ñêòg>‰R8ô¾ºóC¤b »aoË„Ù`B-ƶU¡¬ ê¹ýš¥óNÊ+PTX\ÊÐˇ Gq²×ìe ËAÅ'*ìS BzüÔ[¡e4Cÿod⠞νýÃoF¶ˆüKb§ÉnŸé6ƒ`qªÜÀÏ¡ëΈ䪲S8ÙnL` ª•“·§O²tŠæYTy˜3xO­^HFê`¹Ð¦+ëŸhÖ­:¦ÒRņ›–ãà¡®;Ö/JsÛè`¹Ä»¬DŸ°Ì‰OÒטê`­ƒØeAl‰;ÀTŽùBx„ÿÆMË ÄÏûU¯i,Ù~Uøi1 LenÌóH^ü7B²gƒái;Ô[äT ¥Á*'ú”Ác_8Ÿá0b½ž9G%ÖÐð>«åT{ƒà»^@Gbôk;e‡«¬·ú›#}µ|Ö·Ô͵WŠÈ!¥s4 Ðu³’óói þä`ýPC¶YPV§—+<µ×õs™ñ0ÅÖ‘áƒã„íFÚ:ì4{\ò„sW€¯nžñÏðrïØÀ‹Ú‚Lʵp¹çftñÂÔ¿ùJR­$»{8©ÄæL­ûn'Ç‚µ‰“~Õ 46ñJtº­Ý‹=º /A3%¿("…d•™ @^©B.ÀùÂßZ§g›²-J>ÅØ@!ÑSα‰#7~7c:ìôF„^Ê'tQŸEë{›ú»°Óãv6 c!Kvèp“MÅ­<7Αáwkš¹M¿>œ.<€øhŠ†Ô»9ó²á,¸¶]HâµðÂNêÄF™ú`{§©×Ô¨û‰¼6¤ªo©ÈyÄÙ6R¬Ñ^ø›@sÀ®ÿÎK*8òõ³n&”Q žõ™Ó}Óí‘Z ßyÍ·/„~t°ß<™$m]¼MÆ5¤µPÊ<¹ßÛå0H™ D¯&çoŠôPzp ­užx²€¤-'K¢ |^B Õ ’DH뉎9J3¹öZ…3S¿$Ö1LÁñv¹J¶’-¨×6¿ŸÃÇoŒjVZI$ìhÔš‹2‘' EV7`ÔJ¦ê7¨ à Yñq rÎnéñÍÑšb¬ø#ò¬ÓiÞVœ³_²(¯¡HtŸe%¾DfÑö†B%òaS|aiÅ<ä mïÚ„,â]¾O9·PÝ“;˜“žóz*ÅþUMmî¨Ã ÝWîU´=‘h¥8ø•r”£2õVé[Edž’˜ë¼GÈéºÏ¢­|šKÌÌ¥˜JaÔ¯@jÁ ¼ûeUý‚(O%ë´t¨ç£}¾‘Í~Qßœ«¹5ÜQègÙy¼(­Ä€¢J¸œQ#°ß³%‚?ÝÝF#Ú–øÔ£xÙ’bäÑÇß¾’&ò³Ç9B’ž IøÜ2Ȧ]õ-’PÊ ÀX§œå{¾ã¥ c&;ÜÏR~eÏó–Êá¹×£$Æwl®íÞl4l+Ë‹tüBsϳ+:”bx0¹kÆnüº=&ãðŽC kpÀ»ÍÅ>b-™ãjÞTÓ’ aH-=пæÒýÊnðÛ)þ¥›,y†àqÛªM#w´Uí]ŸáB_×nš÷µNdB—>î¶ä'ݛԷғàí™ekQ60­WpiR¤ðò¨À¶28^Ý'p9`qä†ù8JX'œqüÔ MÐ\¶§ò6<°&Þ®-0Eòø¾pñû7½t$¶×>i€AVÇKÖÏÞKcõD 0½á¥”l®è%¯ÞÕ=hQìÊ6q®ü†×´ö†ÀIj¹É–H¦ßIYp±ÅÕi𼕬™dÕÂçþ‚Ák?d¢úÁn\18ר„'عÂ3 ];ªê4¦:àiž¾æá+Ó¹XË¦ÜøUQrî"ƒ9ot—ÉŒ÷ "1(ñžº!‚ë÷=áÀcM¢ 8jåqà[õ;}Þ,Hâû(æW¾¦a Ùs™H¾µ¡«ËþŠk>Äx¸¤žN>àêÉ=µŸÅ E;Å…„úKXl…”¤éIlºÂ´£¸×1ü™*OâU8â%‘ʨË¡v_ê[*¶ò›ËÙÉw|¦Ì/®‚‹hhcÊø&ÊÆ2Òô“Ç»‡žS_»º¹A[ƒ›”mRfÄ ŸŒYm‰ ™Gv\K„Ž!@œ„¯Îwø}tGÌõùæc‰Û6v;ø6è¯é©žžÝÇë¨AVÌÒ$ÊuôeM)ÁŠ—†ÒœœS\i4éìOæà¿¹³Ž:¥q()ÑfÍ©™w 2 1–D:Æ@Ý|;Ž´ÔHDïv'üƒ+ÊUUv Œòfë»s'ÛM…íB.õ@Ñ÷cyÔÝn1¿,af vjËïa­ VxÓÝÃoЃžÑŸ4ó“|¶íâyK¶tÝànmd¦ìÛD=)žÀ \¾8úÞNÆÑ-bGfŠL<)Îh)fBúd´7dû"ɸ@8ú„è«îÊ¡¬Ãøæñ(BW¡&oó§&&¿œÀ„7ŠÁÿ2OCîì¿™¡/zkÅhF5-šˆÀd¦ \#¿õäî¨WúÆçý檑³!CWˆ  ¥"|ˆºžÈ•BŠ +Ê26Á™©Æú+j }–BŠçίK·žÑòÏÚ`wu\žáM’Ru­µMõoÙ·h@[Ð{¤%7-Ê¡h+úÜ \&´‰ÿŸˆwûÕí{§ãQ|±ñ¡µ9Š,5](}§á Pâç%Mû«“Ï~}V¼ì³ff¥þ IÆü¢©×¢²å; ŠÚ™õ¥v>¼é!]ª«zþ8m)ЗRåN½êSЧòJ' ¨ÔÙ‘²_ÂIâñGo±ÉÉ[•KÅÓÃ䦎‹w+d²¼eæŸ YÞäAPmßPŽ‚E<öÏëU4?ͲíâëêX6—ÒòW¨É·’]@ò÷ 6r¾;7êûsl¬Av? -.×ñן¢žƒô²¯˜ U .f±ã0 º­aѪö.ãÃ- ϶î9·×(B—2„?¤VÁM‘(óð3†ÔÀön'nׂó×XÜÏ0£¿ê~`½Æi½Øë uæ‘ìZ"äZ"æ¯B‹z&Û‰iâ$à+Õ•¬@NÙìÙù2L½ÿ­°ÐTˆ©0 «ñS$¸” ì/óAY=£÷Be'Ò¨ô¤älmM®\ÝÍ|,â'x˜ªˆ•'»¿)¹iNx*Ìd´”âX%6’©×ïBZQTý»÷4TŠÓVS×Këâ±(§'%UpuS„Ð\C «¢¸Köx„PÀ*Ž‚ÁßöÒt¹ê„RñNÎEPZgèÅD÷¹ûlê QЦ4 “í°ˆzHQ`’3ýೌu^ž !@¨Ç+S5Ý|Ff™Ôਫ਼ìpjÎhh¾Ò”¨u¤}v6¬eà­uÔu5{LÀ3utŠ;A¡*¡®åèÐУ/1_9  ÎhØ#ýæuJwÒ#Ý"¸7¡Ž­_#<Ïd}¹Õ~:ײ‹=@~ïp  jïèˆr2‚þ9UÏmpJ?Z‹ßϯ~Q±·žµß” F‚Xu@ø3B-€4!ÉÊÁ;•|#’5áî®¸æ¬æÙ endstream endobj 816 0 obj << /Length1 1383 /Length2 6023 /Length3 0 /Length 6967 /Filter /FlateDecode >> stream xÚW4Üí³„X!Hô¶zg-z´è½—Xv±Ê.»«dõÞEHˆÞQ¢&¢$D-Z”ˆDw7åû¾ûýï=çÞ³çìþÞ™gfÞgfžß9ËÁ¢g( AØAUp´€° èPIû®™$DF0´+ôÀaE¢`øÿPBBÁh¬MŒÆâ´p †§+PX(,~GXâ¤þ"w€Ê`/¨-Ô@À¡(‡ÂÝ stBcËüõä¶ç KIIðÿ *ºA‘0{0¨ F;AݰíÁ®@C„= ŠöýW n'4ÚýŽ··· Ø %ˆ@:Êñð½ah' EzA!ÀŸ„:`7èof‚ ‘ õÛnˆp@{ƒ‘P Öà ³‡ÂQØO8Šb‹ Õµ€ºîPøo°Öo?ðOo€Â‚§ûý3 þ+lopsÃ}apG Ì ÔUÕDû ù`8ä'ìŠB`ãÁ^`˜+Ø øus0PUQÆüCe„¹£Q‚(˜ëOŠB?Ó`»¬‡(!ÜÜ p4 ðó~Ê0$ÔÛv_¡ß“u#¼áþ08Äá' ˆ§»1æá UWþÁšÿØ¡h ’B=€P{'¡Ÿé|Ý¡¿œÂ?ÍXþîw –4æÅþüQ`/(ô„úÿwÇ¿Oaa fÚAapÀ?Ù±f¨Ãï3vøH˜Ð„Ý=a èççï'kìzApWßà¿æ+¤­end¤Ê÷›ñß¾»w>@1) €ˆ(,"*”À>þ;Íß ø‹ü/«öçr 2ªÃ@©ß°Íû‹‡×Ÿµàþ#à¿+è °» rÿ³úV 1=öKøÿ-€_!ÿÛÞÿÌò­þ^HÕÓÕõ—›û—ÿ¸Án0Wß?ì*{¢±²ÐF`ÅÿO¨)ô·”ï"\!ÿéSGƒ±âP„;ºþÝDJæ…èÁÐöN¿7è¯`“»ÂàP= öóUþÇ•›½ öu‚ÂNê— ŠUÓ¿KªÀퟲ‚‘H°/;xìI è/ŒÕ'êók±B‚pÄ’ : €Ÿó )þ4þ•ÖމĪíר±5ÿ:ÿ’6êµLO ì¥CkC[ž+Ò{ ¬Ê~àX5}Ä#à?ló¾ŸXÕ_«×$>+ˆ3޵ )ãxf÷dœ†•-Àx—â›Ï±ƒÃ9C—ÌI|€À/q¢…þ‹"ñÇã~sF"¨W´ì´4ŒxïG8ýï®§kPOú—E½x66^|Ïw§eeoµw¸ÒL+Gï–[2ÈH:‰L# ØõÿàŸr7}f}QNÏÜMÍdžiMl/ý 5„W¨8%{ !Èþb]{±'ãµî›o\,«ƒv¥7èØgÝ&¬Xo«²mjÓMxv7YOçÞ^™"%¸s% 'áÅûØ–4ÞÄ(¡p¢ýT›‹o–Zl´½ÝãkhL—ÒC36-6â+G "YÐs£ÖÅ ƒ¯ô¼D(ŸIÙƒC+±oÊÑÇ·B÷wXXsåûDšRòÃ,QGÃÉ—‡ÃòÚ)‚T]÷ð’ŒèuÂ(ïd‹31>û( ê¥Ó=ÃzßL O Œ6ª½rˆºPôŠcç¶_tôQGÆ0‹¹!þNç~•ºšOå€Ô‹1q–ñ8DÃF8õGmý þuöž;“Y/3N4o©Ï™°·dWÐE«dJ(Ûv.ßæ9W9IåË1|¬¹÷°¤oo.?ÒÖQ7‘›Äð²PÏ®P”üíü|_/œ”Æù¼yÛÙ:kèøåîå ðzbLŒCHùýÕŒ«a†˜›~GµCìé‹)¦DYC<‹_wù¢ð^r]Zq׫÷u+:>\n»%UÓ:2¬üƒÚJ•¹0•¡Î £Iù#Ð.H^PbiCC“‚8]oY[)ñ4¡-HÝY¦ià&ÝùÚÖé*q•]P­Bg²d÷—“ƺõ8²°°«¸§gWŒª/ ò\”«iw(ßSóÚrßf+ʼ2²ly5’6ýs?AàÛ‚ô×&O:E-g˜%^VcîÄu‹ûzõ—••O8G2gx›÷9e`Mu‚sã3u£“Ç"„Ò‘¥„¯ø—¼Ï¥¢û \E^YàE¤WÜçû\®ôt´ÁŽÛ–‘ô/•|÷kÑ2w9Y$³'ÞË{ÇJ†Òx»ˆ7cð½†H 4á3Ø‚—„·.ÆÖF;b;]Èݽn±5ò”Njßr»?¤î>Z|eO¬KA¦ò[sða¹û;Ðõlòn‹R ¯̽ééJ€äñ˜VÑÏn¶Þ~M|8F»c]"Qö#WÛ˜úô\#€}”:¯xÜ“VDhÜG›©}¾ñyÎÜͲˆ[ö™=ô—•à«}ÖHÅe~ÚáÍú’Y°WeùXøµë-W»ß 4´*¬ãÁ‰š ©#’PŠ[“qQñ9YB¥t¯»hç“-¼$=jï]Î2îbhX¯­ÐBE‹Q»·ëVMÒ¹³F8¬U¶ŽKÏÒûH¡Z5GL‘j×i9™‰qª‰rr3ùx{Áæ‘zkcï6£ñmÌ?u²½~£ô@æÇ¹+2ñ¬•!‰]®«ŸhLbXÑ£²óh_$”€v,ÀæuƵ_úØ»Nµ7#ï¾HFm…öOTÏÎ#Yð@4Óo,·¾úÜ~«¦z—‡±š³C·¡i6 BŽÐ€¥m.Ißztsl8Äkš6©Ôîº//Gê-G¦?¸êã”Ï’{¾ÇÛ¯ñãŒÒðP»˜û×m"ÌVu7Qj‡­E„,MŽUŽ«.@·ÞþÂ[6Žþ-ñ]Š÷ñæ•ºŠªqZQšê£×Ÿä•BüF¢• ¦¯N»æ¤2'_}¿œ°9¹Üw,fÓ­= ­ŸÉOq¸{C´±ç¦|‰'D¦(Ï­;Ù–•3Ú(õè±òNÅÈbÐûx˜e;þ§®è­œ#õkp膊ñ4¯[|-Ç[WѾP‰®Ó ©S^s ÁÇ̳X„s7g„o9Ë"–Ïn&·Œ‡Åz0Aä3—½Î‡GêÖ›¶$»|Úy.pN«ž?£ÂoëƒpK¾™{ÖÏÿÁ¾B«q¬ËÀhu”ù.…Q5¡s!‡°õÈè‰â×1?)™È;Ÿ©°TèÏk´]‚[¹ëÇ~6ÀSbÅ{üM±(ì­å "½«Yo^΄ä¾,z;FÝ3° záyoZÉí{…H^®1)õyÛþ¡)…[õyÿ8Éü'¯ñäB@ü-/Pd±Aõ\Wâ‡¸ÕøÝUCŒXceÕ看·Ã{¹¯’'”'mê¦Ý?¹£e[3pÀ¡®V ]Á—»<~0è2E³Þ'ær_~¨ÑjÃ0Ib¤naº<ÈEå,kÙn?+ànîs\F»Ï$`RÚÕZ\ʦç—äÊÙÈbpLι5r¶$s gtßbf™çITyϤ—»\Aï£üµ]ÁYƒÇe:prQI•Ëx½Ø¨šlÝÕhˆ¤ÇU1ÞHïA{Ù§úÚÁÖæ%ŵՋI;‡‰£IáîDÚÈÌ~Í ÖiÌWj@€Ù«ÝÇ/c%‹é?^wޏù9M6n7qi\xÊ”o9ù}â&~„¥d>§ïðvÆíWº·å³Ó_Ç´¸Ýê+° Rƒ ½¢ˆqºªÒÄÈhæÀB>ó2*IFõŸÞङ^}Ãö`â-B9âýÒÒËÏéÞ€ïLM”ó®©ŠN ·× ÞåN¹K2oÙyÃŽ­ÞI¹~ç/êiûBÞû$*àöÒ0€˜äTƒïé£Ô3ոב‰Mq*á¡™/é?$j‘ÚÑÅñ”“« 9±·±øÄÍ}2øz¾'ê0ÃÏlâªÆI¿q_p§²2ƒp8 Ÿ…3¹zŽàËvÎ<˜á˜µö:Í¹Ž§fÉkÉ}–S™­UHöð0{›‚ædJÌñH„Ÿ1]õ^Xj)CÚ·kwkƒ¼6®#݇ÍèÑ+àØ ¡HE«q“ò]j• L´OFL’`‰bpªÜ„ÃHÚ!R'ŸG7gô&€úÞ¸oƒ¨³/íÕõé=J‰€üÀ‚ªJx@ÃÌV÷ãg­•˜#ßGöm³ú‹…ž×c;^4ÅÑL{hpîpØNç^lãäÿaˆß>]¤ lÜÒ¾ZNf…Ûóî‰&© ¥ä L·ûžµ%¬ØC_sÅÆâž©¿JS(bï.ZJO¥{#Ë´ð)BMâ„}â>‚tÃ=Ç¢ˆŒºÀ¢tɯÅBøfB¶D¢Y&ÖÖ<_%ÒMžÈ.ÃMc­:vê%µ kc>Ƙq¾ŸmAR<É=™=2)•°æëy!B#–ùýÌFŠNufx¾|jLÏÀ_ü ²Lijâf»Q}ƒÜ%½Œhj&CLœ7Ø:wŒ™^Ð/í t#ò›ôzÕWλǶ_ þÈð!@(mP ÷=ݨ™*÷Î0³ÂòÐÞ ˜µG@…[oaá{åxlq'×÷ž8ÍàvŠstRHÃbu¹·û8Ák¶R Ha–=¡øîÀÝ“¸Ðõ‚ãkלy~<K!íᦔ’R§ç||íö}©Ê²º½Å9•¢¤.p ˜"%€Á±¸È7|»´{m«Ráp¥&²&Å?癋®ðëoé©¶êWSSV>¬éÕžÝp£0‘-FU,G pw¡&ö|xC˜Ü¤¹{ï|$oa¡¢òÈ«FL‰ Ô™’‚tõð¹Ð_ü®„ êÄ[æ+~¡AîÉî¨Y«‘ÖÒ%~>Ö§k¡¼+ò˜¿dc01á€Âïsv8ŽkYíÃmÕïvQÚ• g§=N.Vö¡,™Víž—‡¶J:m³KaÖ× tã:pt´Sð‰s"ì¬\œn ½qýu5;=&ßYî.ícÅk }8JÎÍNŸ0öàrODº܉ìβ½1)“ák‰b¿ k` ñC¼›ã½=Zc´’ÿ¦ÅجiÆ£Ç7ÙñØ|74ØÕgaÍ5ÿ\:õaSxqH¢,Ø'ÀˆX/¼ÉÐÐ(éÓ0ÆÊÍ¢W»P:câ*ÂGÊ2Óó,`׊ _ü$W_^ËZ&:0óí„ùÛ&ëø9šù`Â8ÏÅòª’ZP#­nÍ’>åFÇ]&ã^‹VZz¥!çb’Û ®–ÖJuÜÓ“©Aîð6ŸµJæÓÂÁ˜®sFùÉ’‰ÍI¼šk&®µœ®Àï›Æžt—"–²©ë3Œ  ÍîÊ”}Z±kÁký²%.}‹L,^®•¡ ±š0Òðݻ؂tƒ…•:чe&]&¯ÍOPJ"¬ ¢nœÊÄ]êÆHdb¡v.å‘8^@giÄìØœqz:èd+L©o5%P­—ùœ§ûµ5GF:ݦOîýï7ÜB(“ßÁK05$³sºIÒ–u$O÷¶KǾføÀ'¨ëŒª.ØSBÞØ¦ë–M,¦öXáíubnXbdW¾E¬>«s`šÙ¹åßwŽb¡Ô†ü>U(×ù0r0,æ­[|ž÷äó­• à»–ÚÝdOOx‹‰?b‡É±[_AýšÎB_ÚÁˆžÛA^ŸÖ4„êú-Õ/}=Uô—O!Ãô£¤ì7à3…ånÆ"å^v˜CYEtó©Â‰íÜå9½´´ÁJO™‰{ŽñŽ/;3b–ô³§™šŸA¢…é7dÍ™Óã–~0ÕùžeìÊðÌÒªåÀ3R¾âv=s0jþ!^YG F´˜Ÿ‡K4³“a­å•uøQw‚çMgΨDÆT–hÐõœUK3J‹7æ/#§às:z7òßž©Ñ¹¼'æ^˜?ùvSetŒ[i“ÒéZ}WúÞn¨k– ÒIBhäYZ¦¾õ:|¹ó•Ã~‚ìBÍÆÝHR¹féP°à^!£—˜OiÂDs{\\¹•Ï…t?\…) ¾>½s˜%tíG!žMú£Ï&–>äQýŒbßúÑÊVÛCwÔS¹tâ-Ê•'«4øaÑër´ì¯)<Ý`Hðø1ÚR•è¥t¼½ÄH´‚A'àdr‹N=}j53Ïf’Öàú㈜~¯¾”®0%Ä8ÃYü”7ÃJŸÀÞ ‘,Ù"±ù>©hc2邹ÎËw;·NèÙˆ­¿°N\ºc•õµ­gßI$üBò¾4iÛÊ6™8/>¦ãd.~û t BÙa!hû:õÂh5Òéûúå…ã=9‰Ý!r–¬”Ç:jñ§¶„{LûuúõÌo‚/*?ÔIz;;Û*ñÈu8Ï’KLëî3UwQó­ï‚xŸ÷–0Eùƒ f¿‹2ëû2ÅÌC¨ÇŸ&¤Í›F{büëÖ;BÇ8««¶ŽÝ’³àq%j&?¾1ºt ¦Ÿé58?Å“³1UúHM¶žÖ ¡”¸Ïm S·…¹sÛ¾ŠcuXâ¨ñ‹ÅúÆ»g˜®U¿0O’‹Þ%:6ˆ3Åí5³Ûgèó„QFôÒÕÈr] ^¿Ú{Eh˜&%9ÉÕ’ø\[˜VQßçVU¬¡Œgi |2ÿÎÀLœ’’×ôA>צxeîÇ|ÿÊp­ÿ«Ä©ª4=ÛÆó öïÎn”ý_ª {‡Ï©kãkŸª»ÙÌžsK¶ÉÉ|fh¾ÖîŽèj±¾ãxjî´Ä¤Ä]àói˜lipŒå.TáDe’+Úæf–«÷=`Û‰ÝF”^ßGÚ0J÷F§_K=[vÇøFÜ\ùnùý’aÚ6#6‚ÚªAb!¶Ÿ}³MV†%È‹•Y!£³’õ‰,5³ >þ ²NIÛB›íöR'ë+²óÔq#òº"x oï¬|z%ÎÃ꣪&®yVyúdŸ[b´Ð}]ØzЈÒ3í2ÈŒ1œ&)áT«»ZÞ?Ñõtz~Œ~Í2¿ßçÅ”éðã¡Ó$pEö|ùi=²›õœÅ’‰¸Œ@F±$Ý õ[é%ÆÑ—2ˆ¹”R£Þ ųgC o±¬úáy0Ù¨9 ÓäçõöŠ} ¶¤á¨âÕJ©œÔGë0hyñ6N†`bRâ(ÄÏi¾îVWg?)ª¤ÁïŽ*þˆ"ZÔV¤ï|£6{3ô‘Qd¿V¢qpùŠâ0"çdº×-®¼°2UóG 4"›°”楌˜nÿH›7Ø•cŸ´¯Sï¨â¬EXèï|?Ë’¿<\#Ì}~o¯èj1†™ážbÀ•³ä ÃÛE9M\+Š+Ç…Çi56{¢Â#Vó—á¬vÙNÆ#»ý³ì%8Y)„=¼Ï÷F¥M¶›&ÓÇ#ÛH×pÁvÆš½Ê 8˜NÅ»½o¾Lp¶Ÿ‰¹|™+þ…}éJÊד:Ì˸œ\²9&¾¡N³FGªý†IÇ[rœ?ʺÿ m›s© endstream endobj 818 0 obj << /Length1 1532 /Length2 7710 /Length3 0 /Length 8715 /Filter /FlateDecode >> stream xÚwuTÔß-%¥t ÂÐÍ ÒŒJ#!- 08ÌÀ04ˆ4Ò’" ’ÒÝ­Ò)--H ’ýöï½?Þšµf>çœ}ϹûÞ½?k ;³¶.¿‚5Ò F"Ðü‚ )€’†¢¡Þ#A„ÙÙõ`h8ôŸ !»å C"¤þ…QBA!蛜2}Õ@"ª.p€ 0@PLJP\ @’‘()€2Äf Ш"PgBv%¤£ fk‡¾™ô×#€ËŠ ())Î÷{9@ÁŠ‚YA Úêp3Ñ è"­`P´ÇZpÉØ¡ÑŽR@ ›››ÄÁY‰²•忏ÁÐv€ÇPg(Êj øE  q€þMN€ gsþ£¤‹´A»APPÀM³‚"œo¹ ¬¡(ÀÍ|€î#u€–#ñXýàÏã þÝîÏÕ¿Á¿C¬¬Ž„ a °Á¡-°ºÚÍ€ ¬!pgäÍzˆ+‡XÞ~o+è 7ÿdèl…‚9¢œað_,¿ÚÜ´ ÂZ éàE  íO†‚ZÝœ¼ðï+~†@º!¼þ‰m`k›_T¬]ú˜“ ô‘òŸ¨›á?9[( ÄÅP'ÔÝÊøkˆž‡#ôwñwú†‡—#Ò`sCê³Þüz9C\¡4ÊêãõïÂ#BAA€5Ì °„Ú„ÿt¿ICmþˆoT€‚¹L@7"€~}þ~2»Ñ™5÷øþû¢OT”©¨ðþMúï²¢"ÒàÅ/$ à…ÄEâ¢"Ÿÿvúû þâÿ;« ý¹¿u|„°A$ÿ qs~QqýS\Ú‡ðß šÈ]C\ÿØÀ$ ²ºùüÿ6Ãï%ÿ/üêòÿaƒÿÝØÿàú ò! 0¸ÇŸ˜e» o\¢¼ñ â¡O ˜[ ·þßÚ#4äÆ+ Û½ó Š€DþÈÜÁ0w¨µ6 me÷‡žþºŽ› pªt†ýzݬþ§vcA«g7oç›Kû]‚Þ8ì¿sUVHë_V@P(ˆán"Q€—àg­¡î¿e è›%€†>$Šð×ÕJŠ€_©ß‘àÐ…" Ý¿B þ¯Ptø'¼Ñ$ñ¯PtþW(¢ÿ …nyüÿCÇÊ…ºqþoåÝpý+þýšBÝ¡V„ÓH+é@ûŠÀÆÓ2z7þÕOB"DÝ/ðŸ|U¡s]×ñW’ùy(œ>¥Ð:¶þs‘|[(ÿºæ™!5è™ù‚÷›p)êéÊÆ[6–+|ÞCä÷϶Õ]„ÖÔZZŒ-„Ö¶Ôßk÷ºÉrÓð9í¯Ž§n>á¨-9)¶ûŽÇYýMàÖ§ÈpOƒÑ’Z–‚šëÒ¨GÕHr0íòÌcêä; NfADå ÎU%•C›g±¸ìC¾Z#,Ñ_Ò' ůü,;®Äô3¹…(“Äšqî;m-òGLèö]ö—¯¨D·{nœ|,\ž~–Óå[xÈK[ÀPj×dèé¶¼=0w,¼ûìÂëm“…=[*;ˆ'¡x(ÃQ[à+{5ƒÙZ=Yô,o%/ŽI>~M‹âwcªü(¿÷sUQ·tbÃ{qê6=!QƒêÇ1‹{)¥ägú~Ñ'ٽϚâìW qý¾…SLD佘РÛ"‚-¬Q ³²Ty»Höb6¬CÄFœókgï,çñëêJ…9DZÝÉ´Þ´4Ã4m/g»*À^üN£þBtHïlòCLi°vÞkž¡¤jKˆ(f”]óDd'åÍÙŒÇ3bgGøšéQzß’ÂÄ@6.üTÚ·ÜN}R<—>ÕÓSf R]ä#áë%Ÿ~AÛ¹d7ºòí°Â3Òš|3\_´#Ù%í#]ÕwùI‚ÔûÒ‘ÛX±þdÆ@Ÿ÷HþTþÞKl Ú‡¯d© y³£ºmÊnØ­Ü!¬)žŠÃâÄ¥<; õ ‘êaÝ#kiµ7q‡sÉPéz¢¡z;möµA.Tíé\·Ûn Àè¬xjÕR´­^Ù9ú>7[Þ:=³ü„ÈÖÉz[:ŽF<±TâyÚg€˜YKs¼—j~WÈ |x¾’MÆrÉ`)QQë±ü"e:’RµÀO`G•¿`LüV×3¨'Y˜~GŠQ^Ê‹³WŸô1ýrŠñ æKîHýVÅ×*ð¹ä,Iq0YGGÌ´æ­üý]¤Èwý‹ évírÛ ›Ét[å&ŽTt{ïÚzº¥ów¢÷k[>èÕ乸ON\’ø·X°)<¾ŽÆywîæ¤…˜Lc7´È®êì2yDŧYÕWñ ׃De1T]×ø§¯­……ëP“œ÷‚*(¸¤*s(’%SI®Jh1}ÁwŒJÛÄ«Ÿâ·X㠤ᥠOûªç\Š™ v^eàœKÔúÊáÌÁ8ÃØ‘\â=q-Éj›5ÖGư£P3²¾$c ¥YYr6ƒ©Fpb ŸJMÔÈ0{%Ò"ØæÌ±›sâ}JÒYP°×ùÂrAkÃîg6ù²Ë]<y3èX(‹¢Þ«¯:}žï¤ÞÚ` £+‹%´# -åÇžè4<¤ÏfSäbÑÂa—~™ó d9ðÚô°HäÛ(Ê…Ø«tÇžú@7p†½Ëèc:š‚ŽS/€^ý’ ƒGóÌx‘?ü X&ú«å£Î‡í8©ëîÁÌw€:!•&6cõ/¯Ÿ3p–ñæ*âtô)ùвªÃ™XU‘ ·ìÞ.ù¸/ÿ ŠUSÛ¢zâNNæO#"ôU©]t‚²³9–?xVkpFe€“§ðƒ@ÿª-Ö®MGp.áó¡†/GÍ¥=¹¡õšÖòÌX· ™‡¡|‰|£Å ÿ ŹcŒõü·üN“:¥°·ï‹hÒ¨æc§H{å#õnÑô¶m¾‹Š—J1”Û3üö¹3­™!¥øIn2µ'lËãJ‹m梖fÖzñÙeS3òôM÷«—¯´D#© µt 4N¶•×(›Ç‘'Ù bc[ƒÑ!Lî…\4M°k~zÄ¢¨°Ùþ#~Ÿ"ïouKùܼϣž;µv„ü è4ÐÚ¦„}Z“OŽJðmuQΡÃþÞ3ò°<Ë^޼féðeA?*ܳò!ÉÎ]ŠËÌ®¨™ÁNcLŸ{O"NöQÁqdÚA´®TÎ`ƒ>%Tm9ójåEæÑ;´\—RKyR¾Ö)á¼5ÅÙ]NßÖb¼ø†¼-eÛä[ƒGM½,‹”XÜ5·¬'ì:Ä"Ã1NwÏ&¾17öhL1dqžÞl­¥×BåktÄFX}ù_A|™$Çõš£IÔµµ¸Q#eÐ~šÜ2Ô˜ý½dz„ÏŠò­]8çŠjÍ-¤øøÂ¡fÊÈ<“Ðð匤pL[ƒiÌJ8Îü]†ð(@ îX©C¨nªÂŒ«wȲ’˜è»L>aã‘÷~›”•Ul©Ë¾b»¹µµ7Q2Wá;Cå¸'™-¬HÚø<ìóUíÈ/ÞæÞ³Ö¼û ?<~\ì‘/a‚6ÌÕu¡Q«¬RŸ`æt·¶RÐRmµdÄt êäãïþ­¨xúêÙ¼¢Ÿ×$ä«á6EXùDÉ>¿LXtš¯·„È»PcA!á‚®õIãà6gÒŽ5åÁ1à§ï|ž‰ƒ¿pn‡¤ iWö^‹afT+ uybðAÕâÂRæb%t®öZF¼šwH^ö –Ž?höcûÜ­†ë4Ó–ZÀÚ³sÇ 6?¯Æ+‘^²ÀF0ÃdôCHs?ß-WuÖ'¨¿küq­zER¦Í—–ØÝÜp¯uìÓŽ~¸9^}t’íÝFgûçDöKÂÓû&?„òeuà(Aû>U¹±¯’ˆTáÙÞµûÙû!Æ‘s\Åôr‰ÁhVÌ:`zjRyÆ®‰y–Qµ ÏŒ[98yÄá:œl´ª¬è$ñÈùãÖZáV‡¢¹e?©‰òØ*Û\B¼m×ôrn*J/ìôR<-&Œö]'2ÅOÚ–"\B¶˜à¦ŠBÒisvÓ 0ã!¤féîøA!Õv6 /5-±w§ƒ+‰ä‹\6ãîc–úÏnÀ Õ’:$Krû׬>­ŠR 'ªëÖ³s“þg?‡N]pVF|ÊGfô{”ð ód\ŽqÚàü©óÙQ™ÚòIofýÃ÷NƘT˜¹j𝥠4®Ëìïéû=c˜¦S-¶(¼Ã¸³— WLŒ«í8s4`Î=âîSã\™/ÊÅâK½ïÄ՜׾sK ÛF6jìeÿ±[ánvÇç9«¬ÏÞý^›‡º›¶­• ]\ÚZ·ÍìõFðf“¼§¦_-¼yÔÂ|@®yÄd¼pIBô›–VÄ^L6U›ð‰tÁCô¶Ÿ%<Ú³-Â`¦-meY‰~_Ž[Š&#YÜ¢ E¦‰¢ûÝcãfÞcë¢ËºàL%dbÙ©x‚$ã¯q7¦ËMÃ8A'§1¡@ŽWìf«‘7RJeî²Ìo[z>YïJ©épÝR]†£Î(F¥rÃ?ö xmè(aç8ö³™èÙÍUeû%xrr3<žmᚉÁ0XuÍ7²¡ÿ4n&`+#'¶”PÿŽGSq0ø±>Ë•åÚgü:¾¸²¶[¤óѱún«—-ÌÑá=;Ö]ú£-M{m‡Ž-*Ä)b ¯óð ã^k3ß· ½-eü.éöÅ]£™A:¥GGƒ³K±MܶÑK`š>€ó#ÊæóO§(Yö Õ.ʾ&âž©yû³ÌѱN)éÆËe÷Ž*=CûçsU<»^>†¯>h*ÿV÷TcÀü5ßAvaàãó±8›ûütR߆(ÈQK •E£îO‘h~µÊá¾ú9li€{r ¢Ý¶`®¬¨AF²ffâê GÜj倹µ*–ï©6Z/‚ˆ©xÛ²cÒi"šÛßjuž+&n+ ›ÔÂ`à¤Y·3ÉeæVA­ø*ÏsÈi(b£"¡+ ‡îå;æDuS“¶xÓ˜ms̉»e`3Y+lm U‰ÙÅËà’:7Na~¬qã»75‰™·ö^|U)C /()•¡¶ñ§hVçà,Aëñ¸í/ Ì·cŒ´¦=Q ù Fiäz³µÅFêkš¯6ñ>™: ÷°ªÅ£…^¼rŰ®Ððs>yðææ ŒùÖ›5NbÊú…ÕØÕ¹}o,^Ÿ¯?L¨ âB¿n.~4Ò’®‰{+'T«‘hãs°mråÒ¼'u5g‰"ÏmL2ÎÄï QôvÅé…‹¸‹äxSØÂPØi!vèÌ”¨åãX‰=•à¦å}NG]{EÏg6b4ù—ÄçÖŲµØ×ÚÞµÛ«Ó‚ /†FX;³_)yÙ Üõ§áª¥Ò.(Ïa×¹û¹ÓJ2$…õ ‰Ïº+íŠw+y÷HýúË×a2~³©Ãxw’¬W÷À­Ç½ ò"«ª±tú{£j «‰Ÿ©û?Í£€¶yTÎ?»…¤Â2¤´Ç†’™¬}Ex:ñ†ÔsûéÅÂBŠÒ¼±¥/¨úu…]î¶ôf™¬ï/×9MQ–>Ûá$`ê~wÊ ¯:æ%b[›£¯¾¤J !q÷×&þ!~D¼‘à㆟rÕî?{óàݽÅ™˜ø=n}~Á?<9N±ùÄ‹¤N€—ÿzg£àºŠØÀ@šB©ÛÏ‘ y‰'XØëæ$<3‰ê1:\Rà«¢)‚Ñ'˜Lü…ð´çA–ƒª+ Šó‚Ô€•àÔþ箨¹V]“R„Y’Ëgði Øëa²-½V.­ÈH¢Ùx;.S§J|ÿ[~ŸF1÷cJoÊaŒg'¼Ÿêº ·U\:É„¶ÅÉBºYß?ž™ä~øÙú'8Q ³‘CC/_’(è8Z§â^–"á(-çnÓ팫áç¡Æ ÞœõÞu ;,^aë©3]îd\h ™ª{*ª)nn䇯a£Ú›mHóOAcB96›‹IÎêJuú­ÅÓÐ+že;Öãµb1½9çŸM31z@. 4 ­@“~žcÝ­úÒ³Ð6½‹³Öz™Ÿ¾•íª. ÙßÏ)[él(°ù³7'dZ˜¼ÕÉ¿´ùÛî,¾ðœLƒ>+™æH;ž«àç ’t•²š#YMøêN[±Ýyá²ð†Á£Djmji{y\G!*€ÿóF|ý*ñrBzGunM2–VÂ>é¾RJC{d‹ד0¾d#/Uºƨ½hCxxñ·”·°Gó+õ80E‹7~$rƒ¦æÿƒ\¬ÓwÀ)B–‡"ˆK;ûÛ7üÒLÝnºêƵEiõÖøssN“¤c)†ÎÒù&c¯§±¢?]ÀÙ>½ó(Dùµ8¯}ލ¬™pw9\.F TΉ]h¯÷Âít‰—ø-¦ºQk•GÕ.Ç8|F®÷64¼7¸ãÐ[_ØSwƒ³Õ$ÿ4$RÎCa/¸Œ…½µêTÌÑzßXMßVõêz¨Ð,Iž¸ÜÚ²YúÅTΟ”»Mø%¸GѰBšüâ =áéãÒíº²ºrS•N>#žQZGYÜMUÊÒÛýÏ3=Yõó°kú°Í—j+‰ï_cGÕŸŸŽ;‰^«™tÛ‹.•ÈÇè!Æ‹ ¶°Éjãê«>>Mö™'ip¨÷"´Ugë }}©«?1V–¥×¨9È‘Wþp5¾Æ¹¤QŠ ¶`7ïLµ>xBÁ\}ÛcÍßó}ì圿'„×a~ïdˆ}²©gxaCš>Oø§Ñ{ÊXËç*$FÃÎq¼Üƒ…v÷ µ±é: j~*ó0¥¥‘»º¹ŽÝ^M Új²zV¤_6Ï ‡•šºõâpI§C°h”“v|,<$è¿^¿dÈ Ç\W9ñÀSû PHòÀìþš<ÝÙ>ßHKöŽZ ú¢–nJ÷áIxv_b Å»^'iú·žÂ5as︨š.¥sÅ{ò­…›×*{óûœÐMWµìŠr·Bšb6üÇùËØ¯÷äÏÝ 7×ÛøÈƒÅP[Ú\q´º9M"¬¹ ,þVg2dUô>Jß„üð¤&Gëv¦oÑ„(•Ôf¤›åå Sm¾gX utzíMÂ^õRgÙÖº.h$û 1‹„`á·åíyÿÉñcn0™»áiþ5£×Y$˜×D³½ò`_óø´;n“Zê¥Õc¥§ÓÁDCeòKÞU\ˆú’!þÝ"S_uëÓá5‚Åœ3ÑÉþÖçùõ½`þ·r‚ïÛ‚{ÏN: ̲¶8Ž™:¶R“K’iü„²v—>ðÜéáµÇD÷|8e}Ê;‡ÈzsØ3ÁˆÉnSËÐgÙ,¸õ´ˆÕõ8™4*µÊö.Á«•¸91P‚Föai®£hå@·3Hd‰wš­X_h#ÞrîešF g¥„ýfÛÝ%Ì`®“II3Áõ÷&`msùF£ÆÈ%£kuÀ…êQ¾Â®òkñµ‰MšíŸ4â+öû‰ÎÕö15:§= §)ò4B/Ëñƒq}jj'Ó+£mYéy)ïD™z˜}ŒÌZè!¸ªÁoX‘ç!·NZÀ̯\ú~XF.f9òC~:‘ è•¡¡xv8!èZ¿oþé¡q@wyV²ƒ±•'Wf«­r#õ³×˜¦‹~w©pK$ö¥”ñÖàßIýÒ½êBk]{è)òÄßÞf3¦rÚ¨–«ØQl§`õ¢õôÒ;¢×Så¨jÜÕáK»´bìå ¯pêw™îîúæãH±È_|ÎUR£–̳ªœß}~NQß'0îOYáâöT§Øá~{<ù'îõ†Œ·•Ÿ¢à2_<­4GÁŒKl¸ÁÖÂ!øLS;’öl“"ÈtÉ8,ÿ\Øï wQº`¿‘kœ³¥Šä®×™„ð¥ƒËËáJ5•_7 —©ÀtŸ¨œ4Owü”A[Ÿ­°YÍ÷>V 9EA“±Ü¾j6ªë9Ëeºs/Gã/¹w@Òª €¸—Sz{×&îÓš—3;äi/f·³À4â·¿à9À?6÷‡åñ–GIÝ Ç=,l g`>ÔÛaªä½â^¯pG3¼#¢‹dlï½-†ÙÉ;L_Ãz¿ð½}*ü>uijjP#œN­>,”ÉI—Ûѱ‘ ²CZ×? i˕Ǧ¦ý0:q…,‹—ð|Z ”Ô-Ìò¢ ¿Õ‰?¶aT§qÌ Vð,{1B…LqDcùHR±É½w§í6axøøl4t“Âa`>lv«’‰O›îÔ'$_[ c@…­ß}Cݘs¢<ýiÌ‹ašig¦'Kc¯ÆÜ£®fĠA÷‚UU&VÛøu4¼õÎýGL/sŽirýÒÃŽDØDñ"k#¶“a—G±éì™{û¤ ¾“÷“rOÝ¢¹ŒZõÚàñ4²yǺwÌ„Jg~:ýüDÏú8ˇjgüèØ³jxvúûòßÃæhy);’¡@•©Ë^I@ú–ø·.\ì;DC˜òS'¬Ò´k±éCåÓò +9kØ>l'éq÷tikØ~Dÿ *8P•!K&[uB¯C³Ä¸[n]òeöãgq¤D& vÊÒ_-Û>ß•×H— >uˆb×·ôü ê8Wàü¶¶ÞÍ«£?&K|‚¯<ѰZMÑ×YÔÌÙÐÅzÿjÕ€ÉÞˆRïDæÚYmüØÚ|gÕ¸žØâr¬+/¸âèヅÉLQtÞœ{5"5m,á¹K¹Ân‘ðî àÛɀѨîÂ.s¿cêÁQ®ñ c•&WûröLÉ—c j»ióœv$O(ƒ/EZ‹r–©]U'±lÛÎEÓ³pW/ôZSg V¾ÊE`õÅn¼Æj4^")l’Õ/Kˆ—¶¼ÀN4¾M1åݵ ܈ÿ9¦Y˜'ÇÁ'åþ¼Næ\'g’Ïm téaÚ<™Ã$ç›’-Ûê&t ‘•mùÁº>Ô50‘Ô‡tÜZ•œŸá0~­ŒJŒènÞ~Ä «Õu‘øoÓ‡Ê_~ 7ìÚ#õX¥ë½-ÏqAލO_Ú(†õ]Çö˜‚Óg£ÚšoÇ üqµÂw‹¤Š2±ž† Še«º¯JâÎÛåRîtV]³^qqyœ_èÆm¢'NùæM´54Ip<œxšñP9¥·aHuùuR/q·ÏC™þX{nçœÞSDuóT"/ŒºRÑ"Ÿ”»)­hS<…½Br”ÒŽ›°´J»¬ &ºÊ«(µÏzQw84x²Þ€5wŒr¢xÊÛ°o°åeª‰ÎÑ‘E‹í"î‰PÕÁOãR¤ãn+úQƒ¸ÉŠTß¿p3 ~S2éS³­^‰q×QíªÕ% ¤lwk‡¼˜èærz 2˜§'ö#ibÍå-%¤»ÏKìºe–¸/øÅ:ÞrÝ,¸å{7B¤lä©’åÆ)$? ÅÖ1/#$júXeë´W‚!|–@³ûÀ€ÒܶòªsjµF4œëL‚q¼]\Ë{4šá; 1ß`ürsÆŽ СQÿžKyêkž•ž˜XÜ?â›`« ëF#ÂÂ@ØÂÝþˆ~¶ìuüìlðêµ>j~®ÇôÕ[‚¼¤©»½vT»~dæ»N;¡Æ™ðð"©¸Á‹kk =ÞSÙFwë’8}©ªbÒãw˜Ç~}zýCÕ…B º‡øŽ}2u®¢Í}"^+»v;ÄPYÝ3º¯Œ}fF¡ð1ÌÒÏM ¹œ½óº–·»sO”Ö槇ªÃNñõw^Òæ(k¥§Ø(UŽ_öWàk©z·Ók.WÌwa¨bARéµ:‰#øF«}ÈtŸCX»TÇ"êj_ße¢â»öÚæã`=S:65k~˜„ù¶Ÿ]¢–ŸåY=ÊwôäûdZ‘Gm¶p!椥å4pQg_pßx¤@Ç£‚¥ó¼ë4}úÿëñ* endstream endobj 820 0 obj << /Length1 1520 /Length2 7259 /Length3 0 /Length 8264 /Filter /FlateDecode >> stream xÚ´T”ï6 Hw ‚Ä‚tíÒÝ„¤¤ËÂ.°Ä.ÂÒ¡´””„ Ý€€€twJH "  ¤„ïê¯ÿßwÎûž=çÙçš¹fî¹æžyØYò+B‘605$Å/(’(ë(* ‚ °$DÈÎnG9Ãþv²›ÀÜÜáH„Ô¿(Ên0 mS ÐL$ åá ŠI ŠK@!Hò/"ÒM  ñ„C:-$æNÈ®ŒtõqƒÛ; Ðýõ à²åJJŠóý(ºÀÜà¶@‚r€¹ O´…8 ‘¶pÊç?)¸dP(W) ÐËËKââ.€t³—ãæxÁQ˜;ÌÍü Ð…¸ÀþÒ&@È0r€»ÿá1DÚ¡¼ n0Úà ·…!ÜÑ1(Ì €>`¨© Ðs…!þ kÿAàüÙ€ €àßéþŒþ•Žø ±µEº¸B>p„=Àî è©i  ¼Q|ú‹qvG¢ã!ž¸3ÄMø]; ¦¨€ %þ)ÐÝÖ îŠrp‡;ÿ ü•ÝgUTéâC Ü Õ§wƒÙ¢ïüë~H/„ßßÐŽ€Úýõp#à=`š*’Ð&Âlö0@$!.À`Þ¶À_Gù¸Â~;™Ñ*ü\‘®;´X܆þ#ôs‡xÂ(7X€ß¿ÿE„‚‚(ܰÙÄÿdG›av`ô¸Á½ ô @¿~¿Y¡‡ ŠD8ûüCÿ}Ë@}%-3eÞ¿4ÿíURBzüEüB¢ € H\ Ž~ øož¿;ð—úßÖøŸÕý+¡& øuÂ/èöý¥ÄóÏáàúsu¸ÿ=B‰ži€ëŸ°‰‚lÑÁÿçEøòÿ7ÿ¿²üßWàKRópvþMàú“ñÿ!@\àÎ>RÐCíB/ˆ½&ˆÿ¥>„ý±Ö:0(ÜÃ彚(zQöÎ÷î®÷†AÀQ¶LÒ_WNï GÀ Ýá¿><~Aè|èÕ³uB\ÜÑö‡ âŽÞCÔï»ý…aèMûo ª[$ô×J ‰Š nnBô< ‘(z<л …yÿxPD¡Ch¹;¤á¯[Õ™~#Iqò’mÿF¿ªBÿ…@» zt€ˆA´×õ_Øã7üOõ¶nnhy¿g-í/üûëƒyÃl Þ#m¥CkC[ÏkïzñoŽÉछ ñ<ÂGõªN?&f¾Z¼_¦¶Ð#¨öȱ]WéñyÖÊÜw¿OuÌõ>"§üÌjŸí™mâßÿ<ÅœIò;c`}OÖ„‘û0E‰IªØ­ãc4y<Ô¾×ÌŸ³¶{>É‹ƒºDM\+¬U·­£¦ä•6 ƒ¤ÉÞºê­Í€Ñ¦èñÎìu—¸ËÈTÝtÖû2m„‰^ÕäkýCK=ŒÑAZžÁ›‡lá( Ué¼j“¥<Ò«ìbÏÝtJ?u*…]hoÕ¦?Œ Àc²j2p)eÙ#Ϧúr¿à¶š6T™À÷½]Žm£ß”¸ÂÞB©zKëphÛ!LÍüéö¶O:_ÕIöBE4ÔK¢dÓKJ]s8—6ÔWÊT„ sˆ¦q;Ñ xG§{KZä X‹ ÚÉ#­‚ @îrŸuK|Ñ 0®n‹0ô(ð®}ÿ¾ÈÝIƒï ñ¼~1QWPBÿÁQ­íc£š×)•ÔOmU0ù‹Á-éþÜ­ÑÒø7™¶2\·³M|—D[Cå‡~¼”ñ34‚Œžß›‹5‡àWL”:ÕžÆdu}ì ¿ µ¥®Þ3¡:Ъ˜‘‰q®ìþþM†Õê§7 <=Æ‹r öŒ–.†*¦¥9P¨‚ã®](ƒâ*|y0ª9ØíòÓCècTܰ¨bÈwœÏœkêã0¥’0ÔLñŒj·,>lÝaL×ò¿5ÖÙÈšÀ]ÚÌ!É¢Ï7ù9ç¥Uh&ýà„Zšo­~¹êùÂM“£\¾2°|²°ßy£ÌÇCQškŠ—Ç ¼ý¶ÂwµÒæú¾ví°¬m¬®®|ÓH%OöŠ<‚_uw´}SóAÊ[¢ƒiJã„—ÖžnV‹ðÜÔ“L7sÙ‰TŸI¤gùÒ-¹úè¼ØÍ|qìáQ“âJ>îgf9ðÉ.ð"ùÎÆÃ“M}{CVuGõƒ¾r®Ã%òïþz®×Úöb#¶ËKÈgi³©Ã*B¸[¥°&¸ˆbä=ñp³„cÇÍ:F‰‹“hu‰£À› õ£¦–®f9Ç-Á· •"ë†@[3TLÆ’`ö+hÞ™ ˆÀñD¤£xæ`1yrk>|EÙg?‚}Þ4ÿ¡n­ž—þƒe=ÕPOp´­ô¥7*¯ò€ø^8¾ô«vêV‚ðr ²!r…ñè‚´¹U@ÙõæX„/9«Q½•+ÊÌ»Ùíôé~bPBjûgÞ‚H÷ì‰ËûSÆ—5«uŽâo?4}kðösqk´1 ŒS22:½óÐZÄfíǧÕ;“Wà›™vê-ç˜@ë7þ{Ÿ©Ž™Îªû WWêOõ!£fa–ÚÞŠÃéIN[þ N%øaܾ«{FO½.«•Iü Šˆ_èȾT$d›nÙ}!xëÊ÷yØ<΃³É¼@‘ê™OU‰É}ÛFÚFÅZ²˜U> õíÍ:ŽŽ£6ÚQgAn—!«òÌ)äÆì½tìù—Ö ÑÒ µ€KæuâÅrºðÂPBé4I´ºÕi)Ø-¶¼±Ï¿_oqâIBÇyò³rî³NbìÏx®Ä¢4vL©„ §›çó'²Lù–¤<þóNlÁ\öï×-âk@¦aԷû‰bO§µY¢†ÃsÏ&ºÂ[ÒòM •“Ö=±B‚D î¦!Ì’pÖ}04è5ü&¸Î¥åuVèóùïÌ ÙWN†füÔF@›¢ÙîÀO+ÛòX¾Ñ ª‹¹ؘŒ5qü0^ÏëucµªzK‰S ³0tjqÜ,ƒ5Uhúq_ü%n‡Ay{PkB$×u5b@'EÍÖ3FKñcåדyšxcí¾Ùâ±ÛïU·« 3öŒ®yW!©™îJ°OñÏÅÌœÀÑ%‰vNûd›NaÖU‘Õaéu£ãƒ-òÖþÓI3À ©µ2¤ÃMÅnZ=BÙûV Œgý&^øaÜÆ\®–’x|ìbh†w«ïÑ’–t¢;ÅÜi]g9-HΞ^´ïñãl2ÝeÞ‚ðdÉV/ŒH.$¼º¯X¦Ç[i]ÀÈ/y5p@IDoär4À©àá?I •e®ÇD)Ðfá±µV‘¸39”À=‰fÙRŸŽúë6{°={ñ~¶Ð2¯åØun(YÝ6Vç0²:Ø«åݯ%ô m\g`Íf#¬ˆ3|w×!R®ŠŠc—™DChâø‡®ÕgWõ÷Íßk]˜îuMôÏû=Cå²%¿!ýé;Ÿ&ûÒâ–ÿñºtû"&ËX „z›_eý•ð‰‰ïåJëÃçÅgÚ"ø”óï™VΟl¥peh?›å’*pbÕ }ïU&úÐÓ”˜®ŽEsNŒ^lŽ¶Ü ømÊ™ÆÞ‘‰ç}j,EÚ…-~}ªª¼ñ³#AÚäŽÁ´¬ÙQi6å} ô¾E»¬IA!§™GñÊÃÉS>k1mf– v O"?V=ý£4ÆGªõÙÖYŸ8·bÙ8´,Ù¶Ù]¹°¼RµG ‹®¨Atd€×æÉÎfPæ¿£þò1æÆ›ÛJ—û8ã¥= ëî8uâuÊÕªŸDrMLœÁ’ü×ñÇ¢¯ÅçÆ² >¾x ÎÉr*Ám­ æ Y¡+÷ŸEmD­£›&óùæ®8¢ý¬Ú°9®}VGøäía_²FrÕ|QPHY—NúÝövGyÂŽââ¼]òK°Mh€Ñ€ >õ{Îâëñ«Ý¹=>ýãÏ5'„^à¡É‘~a祆ÜVÔr“T¹Leåoä[¦œøˆCŸŸISD-Ô{¼°˜!柪E—b’Í›jeˆ¬¸ óv]b9lø Ú`²¯W‚¿(_?™gñBœÍ“= g}tÃ+þÚ…Á[]H™´L(ÅUmhw¢eWmæÙ¼ñ²ÂõŒ5¬ÀÚ²ë 1¼N“/J8tÎpþûœq\AW·¿Ñæ~û“¼!§Ï†f»Ž6AT!YêríƒG=®dÓ´t¸6õ;ƒÃ²·‰oá´ö‘íMæå*¥€ó/q¯‰|î2ÂGõ˜{JÔñVˆ×(4/Qz& ®å?zŸ•‘ãʪ»àÈ}zô9µ}ÂŽÈÛn[ª¹c×ÈÍ÷»>I¬*šZ©¼¾ù$dsëIùté ÅÖ+¶Ö m‹Îû§ÀÛœœjÞ&Š´I/Â'¾™³ãÓs±½XÅ·XFh˜f¨"ÊJqæáÌ?¬²ÈÇX©0Åœ²p/¤‘Î×TUªº#“"Ôë÷oº]䎋­Ê±oÖ ¡[«p»Ðªªà@•Dða;%ÈÙþ6h–ÌixÝ¥?³®Q+—ª¡¡9 2ÂY&­)ÂCÈÚÀB_i îE%ž“ëÉÅÂØx¹»{Á­³}©&“ZL®øÆ|É¡£ƒ¶ýÌiƺÂæyñ†Þ "éc˜ú÷ZÜýÞ­} K®9囕Ãê‚N߇¸ë{eFZ·—ŠÞøÁˆë=¶ºY¦‘"¤Û[[ƒk´ÀYT’¤M ³ÃÚ*lWÏ ;L’ŸÊÚ÷ù@<µ YA•Çÿ49ÿÀ’o:BAã›Àbxœ.Ÿ½MT·.v´"ßqA<•’¾÷Ë­âTö«æçyrí¬eæÓÄÃßy.c¦2îá{¼ÆÃßÛÚ¡IeltMóˆhÕUr¨ê¸yóLVwP¥t"oLÒ>‰gœjÙ¶KŽËcÁ€ –M™QöI*½íéåI¥pc|P½gÕ«Kîhà©kpë¸Õd[UÔaä; ™èœž°‘-V'íŠn÷‘u‹Œ³LšùdÔ «}`»‘WõÒ‰o+ËpQD5‰·‡)'µã0ƒÄa údѬnrMÒcœ`¥í›M+Uí²bÈ~aùGÙâÕʧÙײOûæg!¼=TnmV~¸…’TsÇ¥íÃ2DÇÁb ³ h2œ0¼§B²d–Gë壷íB–ŸŠ[î†è«w]›S½$ {PŠ`’‚ï¥B„fúƒ×iU½Y/S¨—ÀTb˳~­è? c`•ÂqK¸¤}þhеy]홌¬µi€z®±ÌâÆh)ÖБp˜€Û‡ÎnºöÓŒYêÝL¦ÓÙmþ±m½2¯üÔàmÓš]?û}ÏÜ”¢ëX¥žƒò|ðB<Ê ·£"ÕÓÁÅгüíÈÉÊöLÖ0ÊûXìdÔÙ>)›Nå’…oÈEsç$÷«K [ú…©¿&|ïûšé‹˜Bq¸Ï—[}¹ôP¿7E$U¬»d“¦ø[}oë¼}wldûçî«0ùC˜úñÕ„‚/8‹ŽóTðhh 2±µ¦Ê̪Rå¼ó.ñD ýò0 ÷ÒnO) =×Ó>O—w5Žëº'-mùEv½‰<ëÍÃ& MÑÓVŽfê€ò§XDß–)8URôi<Ïm¶ísƒ(æ“j5o¯:¯/¾ÆüØ“­ÄºNÝìýy¶ònC¤Í ½¹þØkŒñe³çâ–o/_Þª ÓU»Ì-oOOy0°ëçÑÖâgŸ@æEœ)0H´·ûášñtSË;i!7/™ÍñtÚ„%4õ­>€·Šyo¬3ŒŽÏzE¶þÃãI²üëLº~™v.ò‹>AF¹³»Î«9Y–±Q­.Özk‰cS’[ÛçcΞÊë‡ý*ZÏIZDz@.Í?G•qûËÄŒ§t»5ojüÄ&è÷Sgœv]§Æç”õ ¤XÌ ò ÂUþ7‚"ŒoL';Ö¶JϬ;gE‚#·¦.g‰¾{[_²bNá¤/§qÜçÓÖ'š¤ =Señ¡ð Ï£Ä剛ådmÓôÞ7(=}Ó˜ãâ{ÏÚcºOa´ZÜ{š°gÄg®á`ž<‘¥óÜBÏÛ칟’ÝùNãWIÊž·—ꌠfÎÇù³ÝSÂÑœý¼ööÊTðQ gÏ÷¥7+ÒÒ?¾ :—ùºËœ™ñ—Ú}¹~.¤š0;ÿË4wsta*ßì¨ oUÇ8Áý.—÷M+0Dô¬’Õ7é‚ûlæqĨrÜÈN½FSíÏÎÒ²Xaˆ4/Í)hêið«Ë’õŠˆüe|…î]–&õOëu Ôs-_øÛÓX[ÝûÖ¨ßg7I˪çØjïÎÔ©zæ‘Xѽ²Ù'Û Ñì“U«S9˜b£¢s¯4]û‡WœlR+Tø6.Ì%m¸]ï¦#÷¾D”z‘MI1¥ô5Ì%Aï}t¾õD )ÓÒ›G³vÖ;“vÐ;éåõ\ Oæq=ïË{aË}TjÉÓßùRýåÍèHŒÅ7h_×%8.íz/mÇåÉI&Èpˬð\n&C(†Ú¦tÇ|‡’ Õ"Ú_´5ñ§—Čؔ´áü‡‡_fÓ/¥¼¼Z\`›ÛLÑ)¦Æ[ˆònp©Æ©)jŠãªvÊâH˜uû¢ñÔ•ŸõMBÙØsêN:,!—yzµ´¤5T ˆ«°I–'ðƒë¶Ý™%›‡¿þ%þˆ/²ƒ6„2S|þM`HCQ²Æ‰wÆŒºP-)ר¼±‰oUàÌÿŠ¡(/¨`¼.Á´•J[§t…qF‚ÿîxjL´´Ÿõþ¦±ÊÒ@ñùݽ™üÔXÏ*1œ‡&„e]©oº<³ZN¨|¦/Â$P0Ɯ̿5@„+NÉýô~”Ð×"AâòP!ãŒu" ‹+~öÀóíü ` ·}`ã½ûâN?ؽÞ9Ižt¸©ÌØz4óòl%àîY½MÐaÀ°-:°œ éWyY°Iç-ïmú´Õ9ˆQÑ1$‹;÷àëóÝiß²eïðŸCwŽBÃj–믿xÛÓÏ^oFq··oŠœ¾#7Yä>ŠÔ¡}Òr´p‚ùÕÚƒõÝy4î$Jðð1;á=pQ0Y›l²pÙ/®{«ºC-8ÅÏ›T£GŒÑu§ƒ¾‘dHY ô6Æ@xJôÁR]%“¾CíÓ…ð¯_o=:3àÕòÏ.¿<åÄÛM< $ÔÖk–I  à¹‚͈ ‡h¦Åɺ.w+ǘ¼+$»ŽÐª°_›Õe‰aŽ/üIËã³Õ1(â¬îv÷¼Â2¾¨^gó^"ê]Ösþ>ÃÏÀªÌ\ß±¡çø[x‰)ôŽìyc:â\ûŸ¸ßùiÝ;õQK—<¸þ’tJ2þbŸòt¬*9kåšéƒÀvØœ.™±½b1M êò­¾SÂ)çÊðÅ+bI¦½@ ’âgæ¤|ÓŒÖ$Ö,DÍÃé?÷ýÝ/À¡'ûZ[¢_Ó“¼´’µ^»:KP%á—° p-ÉÓò“¶%êj\ùë–¥Ç|\È©2tl’ô­¬ òB ɡ͖/?m…ž?#¢\½5@ga(¢LWåN Š}ìÙ¡žÁÄöã°ÄÉýÝûªT¾Ä /¾|©Í¾£<µ41âˆÉû‘ï)ù(á©öÌñÜg ×ê›'Ð 7¤RÆyÃD(zÿ#µ|CÝûâÚÓ ÂŸ4Z¹£Ø˽[â­æ=,L×Ì›Ý[Aw'wi´±ôê¾iõ›:“­¾?ÀþjnsÌMбåUhIogèbÍX-lØ©Ý9ÕÐWlÐðFÿ»L$c³_nå=2¸ŠfRhéö‰öÛ¨Ÿ ÙÊ-#„ŒÑ»F(Êîp®õáØcý8ò™:ñFòlà é-N ø†§ùi=˜.˜|‡¨‘x1:ê“eóÓføËÊC {¯⎿£;ÏG¦w›Þž(j–ñÅtf³Ò’Ëj/“o~ùõ=X6êfå¹Jëô›3*Wž4ñhû0.Ü—®%«4¿½Ïñx÷m@i›b¼J˜K?ákƒå1ÆÄýì esËŒýlEò§Œ0µ¼À@7æ;Y"Ây½¡oP4ƒ¡Û˜ÁØv«£ìÂÆ…SGnFÅéÓâ3$g‚/6Y ¿SÏé_•#êë$uº×8å^íµÌŒÜÁhð6 Ð!o“éd\ )_t"xI×tp—wõ«¼†k{©²ôë厢o¶M“ÄœDrXm‹Q&,æ"ù²(Îà;?3ëÇ ]È{Ü”ÉT€€˜DiµOPMš¥lËì»cssm>|"Tâìj~‚•ã]=¹¿]¦Æ?¡z.ë³Iª†ìúÕ=³%û#s§å¥Ã†Ù\QLùƃ8›¯αZ­ñÒ×n-?¾×#F¯ìws’S^’T?X­RRÜ•¸C‘Ôf‰„ºW|´¦4览IÇÍ'ñ5™|-[?LQWIÚ†§ÜlÉB·Æv¾—CjŸtXi„…oólÖŠŽ4à\­u¹ayé]rÖ¶.Y‡³T¨ëÆq¨{^3R/¦ï-Ö…^ÊåÑu­Ãy³¶Ïú²‚Fk^Ìe`ŠÇ§+xÉäÁ|J­NÇÞõ1¯œ²¸ Y*ÞY>ï˜R8¨&°W[ÑžNóY™S JS JgÏûÌÈm½NkÙŠTá7Ú1Ù²ŽËgÊÁ óXkÚÃ8„,Ó> ý`Õ÷MaD^‹(”„6§$Þ‹'™°ÜpWý Ò.¾w${¤­×M=k:Àþ²~>WÕ88UlL±¢{ꘫ#Ÿµ,&g.—ZÃ5¡Ý7}Ù£!†Ã*-)åIgìΓ՜µ‰ØÙŒº ‰Ë—æ‡òe –´!­})èkÀ‰¬¢¹@M¬È»ÌC›‰ÓæØÛÌB/SŸ‹ë¼èè»a²<Á&Ö˜ÿúD "6ð6QΓià§5|šM—Îÿ†¢h endstream endobj 822 0 obj << /Length1 1701 /Length2 9799 /Length3 0 /Length 10899 /Filter /FlateDecode >> stream xÚ·PœÛ-Œ»CÎàÜÝÝ5èƒÃ Ìw‚[àÁÝ-xp   ,@€GŽÜsîýÿª÷jª˜ou¯îÞ½{õW¶§Œ-Ĭqƒsòpq‹ä44Tx¸ÜÜ|\ÜܼXLLúŽpðßv,&C°Ìâ&ú/†œ´ÉƒàD ˆ@õ… €‡À#(Ê#$ÊÍ àåæù›ñȃ<m\Uˆ†Å$úx8Ú;Àëüý`µaðˆˆ=û# ã öp´¹4@p°ëcE @bã†ûüW Vq8* zyyq\a\{I¶g/G¸@ {x‚m¿[h‚\ÁµÆ…ÅÐwp„ýéЃØÁ½@`À£ÁÅÑì{ yáf ö‡‚› Äö÷Nò @ ¬GI<"€ÏãòÚ‚½ÿÐ<Èå?†{ØA<°~ZP”ûmú s€Úÿ PçÄ êþ‰<ÆþA õ?H´ùø7û6Ï£îàÁG†ë?ðQ‡@·ÁǺв=V‚>ª bû/èþ/Èzü €°AAþä},æý/øx2ŸÁÇÚ¾Àÿºt›Sùc['ò7þã­{ƒm° 6báNõá?ke(½8¿NŠ£gü4æåœ,²À€*ÌZn&éå¼YR+W\àQ´pêÑ”uÿ™»öéÌo»¶Ñ‡ÿ’“VqÏžÖúõÂÃ%â|²ßý~+Â[£4YÑRAmêX‚^L)[ûA=&|–úþÏÉ^Ì$eŠBªšÝ½µeoÔI©D ¿}Ñ…·Yè8'cÉûâš¶gö2]3‹^M¼û+É«†`cxtd…p€ú}lˆªgèׯH8¡‚Ø•>\OÇŒj<`Óî0z±É¥Ÿ/ÿ}ÁYw·,ó’{M¬[{Jг7x´¦Ý–´ÖË''²T†Eë7C¡cèÍ?Œèi¿“#m7çd÷m€~ìCž+´ÙÂSŠ˜Žmy´yÅivTÍ)K^È\œ`,ç$š¤âu~o¬ãqz^f_†‡ÖÃcÝÝöFµäoÕí_jÄöÞË$ìØÆ”™Û)å¤ÞAÈç§=q†¹^KD3jPôžsöÀnÁº]°Ä¤tá÷5Ü?ÛsÓ=Ûè¡¶ŒK×4°#ùú§%¦9rµˆŒ³½ÎÌ–Ô{µã›JHpÎfg”uâ;ֆ‹ුEÛ: F%Z¹š¼á9æ˜Y"œCÄÿfÔTÏ; …¼‘¿}Sñ¹Û[rÔî“rÃ)­¹¾Âå{§,Ý‘˜@ Ç-öö6é +ƒ`ÕExÛ×x% Zž—£LgxµbÛL×,fË_P¨_Œ¿( úlëÆ“„ÁF-}eAŒÃwê ºq\ ‘/®3ài‘Îܺנ$È}ÈZð+O¼ÊMÛ¤s„xúãU¢Dô][³ø‰“Ú¯WsŒÎ­.—kL–箌æ™"[œaù_Ÿ:ƒÔÇ‚(V®3ô§´yü¦Cˆ)HÜò_¾ú˜«¸äg­ß5Þi‡ùå{~•ßKõÙCæèÞ^¬Qã‘­Ñ’›«£¦uI©â¥íFýüÏ##]¯¬¹MQ¬(šlpÛ1ðæËö=jª÷d¤>·ß[ñÂó£à;KÆaíôBÁ?Üááv7½D;3)lµ‘Â(zºsÆ©>O‰ÄßÀyRµ,:7ÃÚ ˜zq rÚ#6ü$çãù•5ïä\!ë_¹'™*ÞB—ŸÚîú9òKÆÅ [xÉ—œHƒuÎmñ@޶&3Ò=MRPG>1ªúÙÁ6jðí-Íðùò }•šÍþŽ%ֹ䯿ô!3EìTÄ­Æn|Š‚ ÄhŒ™“T ’àúàÞç|¢d9-”#â&J3~³¢)k,VÁ¯ˆë××%R“dñ1ß3:Û-Ï«#Ð gí´0ŒÖ¦‘¶ÊòÊ^\s¯^%Æ;“ª™k.p>Ì–]7}üŒRǹ®nbø¼Üú¿q®é8÷‹q'RI…yçúàz:ãÁ^õ×ÝÍ?ß'¤×^fo4¢\nô•©FÜfï}²ÀCC¿`2(+ob |´“þæ´€óÌíJß¶UÍjæTŠ¥<ÒM‘\@$±áă)E߯’î`ƒÏ@5$d—Ov‚ÞîùÔ˜>Xõ^u¡ÊÊÀv¦›eëTçäš_&u>ïéf§ê£tïÂz½® d3Ÿ&6·§Rí¹†{¡ªÍä4×h´#”Πˆ|SRß•q»Œº`¢ôOv*쫦väHD¤|slL§ïª ’ÝË«›µXQ{Ì8ŸÓÅ‘Óäªöc)³Qyè\¾n¢Ö¸, Ò'³VJN 8}#»’Ðñ*к"øÍ@)šúéY%©º¶TbÓðèSM¹ê=ËŽÇq—$Sñ‡¦®¢¿â|=åcÿäÄ`ÔŸ# ¼ËøcÎÿG.]‹bÌúèxLë=Åþ’z²˜e–­Nšª cs{Z¿Éëg2RW]÷=â«BUS²¤@»d‘gi‚ _žZòÜÎz°;ßQé=C•âI ÃÀ>[™\÷qa ÝRGl›‚wäÓ"¼&:ú¶‡ÙK^á*=ËNzûZŸDäõ²BR±‘–=çRÚÂû8üZå}èH†ÃÌ·è®8;G®àdˆê—ÃóòŒg5ó.†Û¿Øöå†Ëc £™æLÁô'rå]Ë· ¼½°²ß®´¯ Õ¨ø³ŒÅ²åØêHÀ˜×»¢­²¤€…µOÌÁJ”¹³“ŸÛòkÐeP<8vÛ3iÏqŠ(À2ëƒ+Ë ^Ód±ä7¿:F1ýÁ[8™È•âok(»¦îüû¸üÒmj£\~r¿*Œf-%] ’ÃÈà8š j¥Z|Þze0Ÿ€JñÊ“•ã]ØÖŸ®ñ¡VÂ×u¿:f»0r3y;ÓÝÉeŠ‹ìïZNrv8ªÏHï~¯ìÃS’°¨pø|Àæ\“Ýæˆ)l=—øSfñô§·ÒWb$þ!™ÖUdÖóØ#§š-Eý•ÎiÜgŒ ã0 ÝåÚ˜]JcaÑg3×`gHÇNFÔøÎ:Jð{…ƒ(ëãØgrÕîgýÌ‘wÆÄ‡*…ÙCó(]fËÍ}¡¾Üê‚!VžI›í¶O¡Rߦæ«kÞØ}”›|‚V÷n¡Íõ9æŒV69"“OKÀºh®±Mþ‰“€äråµEHÕÌG­Ô:—Õ©i ªó2 _…¸r_ÆûÐ1›ïkÜcÎz1Є.™$‡RvDW´ªêDò½slgÛ¸’‚Ã<óžÔ“°@!ñF5¥UjΖ´H,]ÄLZ=¤Ÿn® Çþ†ïÛSÃBÁþþÊ@,’Sa†âkD2¤CßúËjÀvMKϯ.Þ”nÉŠojÞî|ýÅ,á¥ÔUÙû¯§ýgŒ>1EsŽKì($J×´§póZlx4‹æ±R+KV‚÷–´ÇWæÅj®>zàjôfŸó´IcSfÒf³x·x×k•&±L†u‘Òs·£{Âñµ’ú*Ò]Žb×Ì”¬¬/A4ÂEY-Œ¬k?F, øˆkܳç/Ž·ÎäPé+<{b[/œî â¥2ònVÆd¨çZv¸Ê`¢ÝæÃ”bʼÕ]õR.=õ6$DÛ÷ÚÅWçt`ŒÂåN8Ï«Ï@ àp¢µxdjòÊó-ð«ß:ÚþL ${2Ÿ8F½àCJºò¤ÜvîÔ˜/KÒtiÍÛò˜s Âb8Ao4>œÁP¨ó,j%ìåN CV¥®÷?ù¢‹Å[š'wz>þ#¬œ\óÿ…ݶ'(÷NHÉþU[ÆõJQükY Æ ôÓáC2ÆlöÁÄ‹›ü º0LZp¥ØÞ^ð¬Ñ W™mà•Ò=·BÆæ$&BÑš4Ïvsq¼·cmŒa¹;NâxkMEJÁt×¾HÑËÇ|}ÁìÍ Œ×Ýõè^*—ës±ZóÍ¥˜ßÅ…~(Ado^_B©fÁñ<ÁZ·óáÆ€í†÷{‰á°Òèbó$s€~Ronû‘Jèí÷lÞUòjÜâ(”ÌûƒASÌÚt¬I6/î|Ú tCœ7_?þ"i}IY1Òîßi¬=ŸoØ5Ⱥï»6sàêçÙõª_Ξ7~šeC€ ŸY7N‘„m)wž_ãÌÎ9à§f*-mFU,»>Î$Çù¹ú½žYF+µ:öÁ®Ž‰uå:)¿¬LÏËŒšÁ ÁV;¬}i½uÎG'ñBáLg?%ƒõP^\¬Á©v`´åf}Qåë5/Œ„º yýV¦Ñ>R)yBSo8ÆfˆwþWû'"®ÈÕ-¡r¯,ädó7c÷jI$V=^ÏX¥ý yãâ^ÅÊk¾Ú“© ¦ÌQÛKán þ&U: åI»:ŶˆÏøGò„ÐJ;PïVBmõAJázG2;›¹ãìe¡‡#/&£é§8 ÷”¯áð‹‰ÁÛJ÷0Ô&v$«|À»+ìªdá¡áAÈkv( ‡êW¡øÒŹÔZÚM‡ãl\L71Î-7é%¯ÏTd iøbsMÇžÚþg5Cý0† aŠÍ¸ÜT¨‚h·×hNî ©‚ vr^e¿„ÊÅþËRÕa«“)ÆlºÞÇkIû¯‘¼1f¸–Ê0Úå•Éò¹Glšß·‘ªãlE¶‡‹º£8ø¨­6Þ+Љ›<äMGü ì÷ÿQѲŽ9OH|®ôè¹+¡­9–°>è.l¼Ýv©drñ=çÎÂv“åµå4ùÕÌšWìH)0œêºÍ^¥Òl:3¬æ'Iëåßø«b³=œ+›¡P¢‘¡%KŸqOEãrÓ'!K˜”¨Aí_ÛÒÃ'a%H1„Š„šÇ%žv¥q,ØC·¾N}“׆ˆµ•GÍA#&›¢´ä+L ¤çeެg|é|±=!½…ÑT’ ÒŽîK{JÂ0Zö¿Í8·®ùB“‰Wž©ãNöŸš;èÖ¢a[wŸþJ ˜ ÇLÓÊC*”ð®/nD]Âý\b¹3(ñLpÇ‘^3«%ò5R&`œì­ö¦þ3 o˸÷¨ ½ëoµ0¢œd—¶„¥"¤Âw¿Ê£vÄ#$R™¾:÷‘OYìAw5*±dH²Ž=¤ù{±ªXmàWõ;‚@þ !X'—jŽ>”žoDFšyÇGºë;é—¹P ZRox™Ÿ¡ÀöÆN=»à'ej>Vž²ü©#~NÆã Ó n ÓGlXvþ(nk »IS~Ufëlúêî£;+>L³é-qÎùÆ3å—ÒI@­IÛ‘¯MæüyÍ'›#Ò©«áÂ:k¥zVÚ–‘}ì;Ä{I `~3¢~€‚ùi'ßÛõR=&*fVŸøB¹¢Lëë­Ö’xL¯'j…XW]ªªÄ7˜… ‚ÛÔ.FQâhü÷?5F-)Ìõ£3Y2ë/ô+þd²Ô‹Ò°µðPõH45†€»•Ô„®¢FîFðýÇqû­WÐ^»¥u$7ä{„n!|ÛÊ¢¶Äïj‡D¦êX>­î˜²½ÍŒýÒ,äÑ£‚ûtF‡X“¯ož4©´ þ|v«¢ÿž1*þ~Ò'{1ê(Q9 êØ¶ó`hãkNæÂ¼¼þV±U´­@«hŸ‘a$ƒN^´ !–!‚‰ D¶•­á|72Lo©ž~#EÕgKÄ~#µÀ}Ìk.äÍú­Š]­-ÜÉNÅ…â)@ ³¿xÕ`®®É}Ìþ³Yí{ê'ŽiI0ç¤|.aï^޼š%ííP°Ë(ÁñÐŒY ¹.ÇFÏ~Hš|qæ’}ä:ƽOÈõAþˆŠZV?ÄFjsrôÄ™£°ˆëýÝ)ÍH×»ìŸñ ¤ÃÒ¤6…ê8Ž”N½bšµa{r²þ¬½j¾´¨´Î©óWÕqß u2¯P&Þ“XïœÉ¿ïl $Š :ÖÏåëij¥ø%·_ˆ .#ßhßp*Ý%U¡4ßñP°3×8u>!5¦ŒÖa®†™ >h¿¿”©{q­­Ü„ºjó‰É‚§xáPÙ¢Ðg5‡sdwÝzæÆÌê/‚ô»ŸÎ§.¢…–EîeºÈ2CïÉú{Ÿ[]õ²¼o3ys´›ŒGšámGÕÏnš·LÙÀ 8ëoòÏ9ó£"VÆÍ§üQõ6 øA–ŸÜ3‡—ºŠ@”<çûÒDÕj>°ò‰Î´©p†§é5„¡5®®l5ö~…?‘ÿçËš¦à¨ýšfµŠQE­/ÆòÞè©À|潓Ÿïw¬gºV¸|²÷mW?´Ê®Z³¬ø;ÝÒÇøNü|€¹UiÙË}Ë}K3¾¥1¬Èðcç=O«>§ò·ñqlccTçtsˆë!)Ö ù^ÍQbÃèG n¿;SR|­%¯“ìÔ<+謗H¥—ZjY¿SêÉЯ Ô­æÅŠB­ˆø_ !§†÷ ±/?Ø¶Ü Ú±-¶¼UDa0CV;›=FÉAÞ ð¹ãVQ¢­ÛVs†Žø{îR »!Š™]Ðvžªrasœ£Ûn.1wGŸUw}ÏdÀÿª{›^|”Þh÷*[*ƒm¼\KÙgø=§)­Ûvpñ=õØâðzß7†ç+ú#&Åï:âµÝøýÞeâ$ãÓ6ª8ÖÖJÔ'Nœ-Åg2«t½šêSMÝíµ-[4Œgñ! a~»JïÂÕYl¦ÎÌÚëÉåâG´nÂQÕ>³$öshB6âeð‡ììdˆˆI-ß*Éà˜ˆ„ï+VâðŒïרmÚÄÂG•òÔ§åGÖѦŸE1,Ü2î:z…'aø&² 5þ}Þð$-e:Î}R‘Jb`I÷Ÿ4¾2ÓâPè ežqvé4ZàWÞùgÙø·¥Wö}e»`–Ê¡×Q]íONCÊÎHæ?J³¯#JøOsꦧô¨OXri1q~^_HÀ&àò»Â©J]SXOùäsq:k[9öû .z.ú°øƒ_Ñ/Q—³|èõÒE Bº¬˜Õ ™ÉPJ¿.që^¸y‰ã¯54ávì(GÉ@SJFè-áê6^™%ú&:©5U:ûP ÙñòG‡'r¤è1”囟©vJ[tM—¦b©ù £¬YŒ£ôŒ<Æ.abȇmŽ<Á£»á¶-Å—;‡zq-¾ꢭù—ªÛM— ä–tÓ"O±ï½D$·ŒL•®´è‚|*’òßÒ§Åo‘fËé#1à™2ÜähM»aWv¤tÁ”m»¤m1;ÆÌ¶“:µ›úò"¬ôÎ)†ÒäM¾lˆ$hݼøuÞ€®¾)ý„AÐYFAnWËÏÒOÙ½ÕP G÷µR¡„ädÇ­ý½wé%»Ád*Œ€$ùvÆ •ÜB^Ð2Êßhb'7Û¹W¯ÏOÕ¹$–øŒ°‘'\¤YSùmà¥ì·˜™Æ x=þFÉhÝBÒ?+å¼]Ѱ»áKÝŒÐ+é ÷°K§È`âR·çÅ‹Â^ I®O¤ŸŸ¹tÔÃßlÐÒ ž¹BàÓ‡ p¨~§ øæÌµnKYéÞ¥)…åë=Ì}GÐÿ**ÝàÍW|úûx žM¶“åU?ãmÖ'=0?ëmŸH÷ù’ç÷y[ã±8„˜7§ä­c»Q¦¬Îßk¶~-ÞÈšŒ¥)uyäh½kHÄ.!´$šöÙ¨ P‡í’É#œ>½Ë°ðÕ­uÁûx±LÔøI¸8° M_ã~Çö\«4Å/œ-@WÔ¦‡RñC¾M\«Îì.y_ï6Ê#(_¡ãlö„Ï“À¾hÂhS%Í*–éîÖÀÿÞºt³Ø’Ib› &ÒJÝÚ8î‚Ë aMÐy¡H*‰ú¹Ôð+9ÌÈæh-'d¶Ì™Vi Éi'A@WK¯Ç½«!¿mÅz ÅkŠÍ–‘øÖJ9œDª‚‡• αú¾–ÚW4νá¿ý< ØÛ¹˜pdü=+î^gŒé©$æ)^¹'`Ü™ƒYâ•Gš†ŽV‚CJzlk R(™¦Fxc…üXž‰''t• !ä­ïE¹‹d³s˜'éµIjMÜ ñª¹Œô¯˜^‘ªõŸwÊ1 lswYy}ÅqÔGì¾ÙòÇrX!WÏ âîDRÒÓ¹ëEÍ ´{²ÙcÑælWÚ¡WÞß7$Â_µà_]˜y`V§‹‘ .>ט’ËìûNþ µH>±€Ì5®O޹¿õvÉBŽgkêG¡Ð6ž ø‘`û‡20ñ§‡Z)h`ªw‰F”=Á+Ã\ºV<’-M×J»`–{Ù!ш’5QÈLqÁ]ŽGq‹§Úù«M>'“ÅÄ`”)Û'9¨ ÒàÞlH¢(#!FðI³¹°N飡zú}R<.ÏeZu::Í]"Ì ™åÙ«nQ³¼×9ú®GØö£ŽÙxõÚ¨÷šÓ¦x¬ñ-Í‚¼´¼ØÉ23.)ÓktOЗNÖ×´½x%˾ž*Àöë¹ÞaD\5íYŽqIàP>ûÁõGÓ\œE³Â¥uÌ^|ÁƲ,–pHˆÄ †ß~çp;¥)Ãe«PÖ‘)ELñ_ξYïííÛ&¬U… §É'߃Ó|_§¦LÈ`*‹‹ÊwüÚÞçÙ+°¨û†ÜèõüÁþýRPAú•_¼ÈWáb7O”¬Ë€Ömê !÷òŸ1©/¶sã"Éâ d°ã†ÎœJÔÒÒHyhyeݪܯ.ì…ñéY07¯“™ú"]3šjï¬Ê '토ð Êä0hn³®ÇÝÐyX¶VúIÌõ ´\úªf°u (<3àËBÌ]ô 0™)°?·õ§Õ‚S¥Ž$õL R–…'%"_‘-öÌêf¼*/À‘ð—ÒÀÓûÆþO¨=á³ê±]q°ÖŒÉ¾–%åxã–{-OfÓFCTa¢6ä{môrƒtùÙ'ºò²“†¹úø}2~'eÑOÁéç7³Ò{ôF §¼á‹;yö}‹òc¢fÙˆÒ÷â“ø~–ã­ÌΗîŠUi£¸ ·¤Ù–EpV9C]oq¾Ýi²TÝE¿.žSËÌÏgÞx œ 70X–@ÊϪê}êc÷U¶¢Èó nri“z§Ñç® ’j´”ÔIcSr§Òp­m£Ó‡+bßÖèÎnëò`çSÎFžq”Yñ/2+°ÕÂOïŽk^H"ê¿àˆÚgvÑ¥oîjOõ;·œä ²½÷]{XRn¨L¸“äÖF•½Èëvô»{ŽgµáÕ=ôOÛ33»×ãÔ §ÊAVɽ™ì6ù«µÕÖEÄ«‘ºNÀÕÔæRs¾Uõ쨣i^üü«ñ(„¤í E;ä"w£miS‡jþyÍ/Yðøo½‰Ä)˵`$îýHÐôò+TWh»ÄȤ ¤Žé&äY–¨IÑ59TäQÛÑl÷¢b—ÛÛ€mŸÉ£Í§tîÈŠ¤¢*Ãjh_B+гk~H þA‘*årº^ 3Å”w“ëd™ï¦‡ôà ’¿}á)4}Ù|ÌSlÊ€ažð¢(Á'iëyÃ>I—_îäÏ;âNdFËúü«ÂMM™u 1Ÿ‹4Þ4N³´rÏ{µðù2|»‡é®-^Ù˜CJ±|Ä„…Ć’[h[‚Id{ H«¾à^X6AáÕ¶ÄoÈÿ¬Ëž’6‰{v?éUï‰ îÊQÆéf|r !«<–•œ Ï<Ì7 ×DÔ#Ⴣbº·>š¿@ÁoTNaöbOG¬ºüñc2’û4'[Ð’ &'±‰¦Ì:I zæmð¿õ<ì0CfÙ©>ŒÇ½W|y`÷’7¹ó™^Óxàz3ÍÅ’+ÇÖ¸ÿQiùç¹ç ë2±Mõ‰³2µÔó˜Œfzí\zh®äD_üä[í¸´Õ ĺŒ›Á×õß?Ã=ßç|é™èëÛDyîƒp¨6h*äø)”=QEH0äãæ•Ó¼HªCµ§7˵¾çºôMžÇ~Ê;V’_㔫(ÆJïÑóJv‡" á"ૈb²t ±o<>“¸íUø9Ô:Iyñ}OYZž¼]³¼$èåÎÃ1*¢ÌÄÚ¸}aËxyžŸé¬Æ§Å깓­žû¼ó…²/nÝ9“~ICM„xáŠÌrúíBdúˆ°›Év©© ÷pçÐÜÂnœ6 EHËÊÏcD''­™:û2üœfW¨›uß§[„!²'ñºp½z ¯†•LJŸô-{ZÈùi̾1…6P²tu.>Ëæp [ø–k÷ûS½! ϶'cZÆòœù²RP#+§‰à7|j™¨/šR‚ÔíÑŸZÈ¡ûjá&ïC«µ1·"ÎW-¸‰eåÆÒ>#ê£ j×=‘H–zÎíTË©á0s!ZþAÍBWUZZ—߆ôýNYU:qºi»ïÿ9'b endstream endobj 823 0 obj << /Length1 1415 /Length2 5992 /Length3 0 /Length 6952 /Filter /FlateDecode >> stream xÚvT“[Ó.¨ DAŠJÇД¡7éE¤7éH! BIè ½‰€tÞ‘"M‚Qºô*½wDŠðGç;ÿùî]ëÞ•µ’½gž™ÙÏžgÞ7lLÚzkýÛ`{Ec(¤ÄÿB( ¡`,ΦÆâ€($ð±“$‰H€D%øùüüâQh  "Øa Ôà>F!¡›ÊÁ €Á±¸:/ì H\\”ûw8PΊF@ÀH  ‡Úã*BÀv@=źý+»‹uàãsqqáÛcxQh˜47Ð…u¡(Új üE¨ ¶‡þ¡Æ `êØ¿z(¬  â v‰Á…8!­¡h ®:POU¨åEþVÿ À üs9@/è?éþDÿJ„@þC ({0Ò „mvP –²:/ÖË #­Áv.ì FØ­p€ßG•åt€`Ã?ü04‹áÅ ì~qäû•wÍJHk”½=‰Å~O†Bp÷îÆ÷§¹Ï(¤Çß;ÒÚæ k'>$ÂÑ ªªøƒ3þ±Á X 0¿˜¨ ˜ê„ºBà|¿ è»9@;A¿Ì8^(  ŽÔ aÅý<0`g(‹v‚zyüoÇ¿wh€`VP ø';Î µùkë?á 4åÇÉäÿõùÏʧ0kÒÎíøïó(«qý¡ü§¼<ÊèÁ#òóAü"@QÜÂëßyþs³ÿmÕ#þœŽÿŸŒªH.Ï_,p×÷7ç?Ò`ÿ37À—ÐDá ²ÿ£3~a~î ôÿ=¿Cþoâÿ•åÿ©ÿÿ>‘²“Ýo?û_€ÿöGعýAàí„Å ‡ 7"Èÿ†Bÿšh ¨5ÂÉþ¿½ªX0nHä0œÐy@B¼üBÙe„+ÔZ…ÀÿÓßÝÀÕ°C ¡Ú( â׃ÅÏÿ_>ÜìAžá.\Ïþr1¸AÄþnï¯=7jÿ>‡‚²þ5“Â"@0 và$Û =@¸áµ†ºþÖ<‰ÂâB€8Î^@ð«Ñ"¢@>…_&À¿ÒBœÐh\ÝßzÀÕü{ÿ{î¡PW(0>‚‚HØV4ü(“£sáYê•"ØIüa$ÀÓ›cA„mW|ú-Z/5eB­Pyü#HÙ¶YSÞñGÚÌèÇbå½wnBßyî)¯ÂîY½¹üŽÿ5Æã˜žyäV ^¦a¼<£D>ºO›!Œ¬…XÆÖ®ÇvËóAEÛXŒËýÛÊ¢4›ZÊ RÔïÒ‹?Ùœ×ÅÖZué/ R?HŸ·ô_xiš ùšYMªéíRJ6×ÙÝ5Eþ‘áC˜ïcg¿¥]Ö ,¹’d½¢ÐõÒ'SY¤çéùί)<¬T(îêid2éRº²bkw¨ÍÎY®Ù¦„ÂcÔ·³^¯äÂQ> '‚­þb é_™ƒa/<¬¥¦•u}šjGƒ»©ŽÇ æºín´ô׳§°x‹ ö½Ÿ–Ó ³M| 1áá5Ì€ŽPf~¤àtðß8®U%H¹¦µçì'6J Çc$Y[Þ—µÑ­.+wtÆÀÛî_Í*+u¯ÀvÏ:0ƒ%YǽE¢õñØë±q±TóÛ‘ž|Õ21‘pâ´”DšËëû¢ŽÎX²›òn+³‹+†U‹ƒý$6s‹wnV¸÷cž7õ·õD˜nüH«£Ð?’ ²)]ö¥¬MËé¤é¦NߟT 3}È,¤D¬^—wýl–4¼p_TäÎ}éý‹ªSEö×Ä^Ñb ÆÖ«]Ü™†çqò˜¬÷Ì 2Èqñ2å'³µL'wúª=–™,`ž%·3 ¿WÁhòÒ1OîÕ]“(VËAD¤ºà]yÝ™žÄgõÈ2ÜfNkú'±p¡%WªÂ•nlô{‡—^iÔÛLÈSSâk™½½¶C¡š Ùj­?3/•m~qä)òvIéÔ1ž­*«uµÁ¡š×('2ú\fÉÛïb’Zl0‰^’slnɳ†ü‘XvÁkr‡.z¢çe6‚bÀó‚­ß{XÌSЋÉü¹lœäÃZÖ¡ZKntì-RvŸeÌ5§ˆ£_îèZ”§áç¸Nô®*bM¬¨n= @M‘°}h#Z©ÉŒ.#9h l+ŠhTÓëç›\Î0Á4‘'R)é¯hœÖ·?Ö‹LZw]ÝÕ^™P¤‹óoW¥`ÈMèßÅ7˜û~ƒâWe‹ûÓp¶n~>x÷}ëÙ”­îçÛÌadqPOP•®–ˆû“ëú‰cö׳J/'l³9® ß>ëzk›ÇM›æ+¶¸ÔºÖqÎf—õÊ®°O¼ ÌïjXÍ#ÚïÅç´Š¸fÝ ÃªP§8;XjŸÁRʼnN†BI ßÇZÙkôr_Ka+å pKºí33 Sæ>Ì(›ÇJÞ*e¤½>忤׉ÏAk6©€ãçIh–UW YûsØÃZ;™Sƒ( Ê8.h/ &B’ÊÌ®^×7ys½°º@—~Öt×pe]-í<\$[ôfLS¢m‹eWröüvÈõ±)ëñÈ$õó­é¤â„jö¾=Ä.* 4›ú_‰ê ^3ì*m«ÒuÓ–pM©¤íóÏm¦]® ' ÷D K=ß”'vC·ï}ê  *VX¤Gzj1‡Þ°ï{²Ú\¡xsBî§mÚi÷#É^öQrÞ”xÃX³ïDî³½zã]Š®«D„•ÒhLøGv›é©© Oq`9Üš“MDn²öih Š£ÄDe*yîE™BÌÇ Û½´Ä^§EÚdûõI_®³aöT4“ o2€®Œô+¿ ¸1„J£”&ЇõQÞñ=#Òl~¤mºÈßc舥/¾î³¤;àrÉ%bU³ÓJß^¶çÝó)­Ç´˜ç[µùCx~cŸSY^³uAXk¢Þ¬aoå¹ã¥\PE¯`p %•âÑgDþ ü\ñ;é®¶ïž°^„ä̧Ц~SANTØ´3 poúsQù{§Ãë/«v/´=Ü*èxUjªîª<¥º­ÿêK¡á«+‹§ÏE»mÓ˜4Ô È®IÞˆ‚Ôä”%À5:8Q‡“©º)­›š¦²™+JÔ´Þ3Ìž¢«$MÛæíð}#´ Î+uiùË6ù3EXê”ѳú×kð\Î:}„VˆíØðTTÆÇTM¨dÅ|!U¢7ÞÓÞŠ Â˜ŽWÉÛ·—Ÿ›S4TŸ<Ê XÕÚ]SZ/b«ÝÏ#ü1{)«—WtlV] ×ïl‚€'—­X…ùýÜëx´¹\íLz´X©¿O†!3.«6³zëئži"¸Ÿ‘Dö¿Z+á­LJ§”¶L¸ÔKÜÔG_½%xëŽe«Y;unäHwGùaÕãMÒ@¯+þݰ[Žó×eŸ|´J¡ŠâàþV¦ºæqJl,+ }¯ØWÑ%8 ùîÞçò³¨#ˆ±ØÓ‡Qª8§g`ћߧLjÍj¾`×>Ñ+w0µw/Ä^£¢™y,Và=PyHã2gOÃâ;ù+ã>ìÖ3)“Mß_¿©gžÿáp3˜å‡Ò¼›®û=ÝÑVÑYªº£·pîX¡»K­Äþ†B;ý¶o´£]MR#yéû¢Oäçß—µØ7+`tÛñ½fMÖ‚!Tù™¡ät3 ‰{g#²wó(’Þ*Û}ã;´¿y[Dx’¨ª™­­7/æŽÔá܆­Jü¥ºšzʼnóᤱWø—JŸå3%šžcãaâƒO¸=½‹C~ú  Z°Ĺ˜õêWÿÇåhÞ-Ë{eªám‰gËdu„ìÑFþ¦&޹ž êyѵ%©5<òôÃbUÕ~°ßÒr& ‰÷Ù´×Ñå—혗µÒW£+³Kª[ü<ò&îœÎíU ר-QÚó”Í)¡n½ØâÞýÄ”ý´Žã-ÿ¸Ý„3³@Äuѹ +2Þ#‰ç<Ö­èÓ•W€°üÁý+#÷AÕK9Š”nTêgC\w_ ÷s9¯ §›Íc3·™ÔbŽ(GRWrÒ¹£Øš wï´è9"^pgÊÊAeõœD»Lú _t0Ý1dž2îÔµèÈ–7„ð”›YÚágK,.°Zå}ØeôÄ×6ý #1A»ÛÈ·ÀGb(GÓY.YЖV*!¤©lѦd®”WÑí¾w·y`4—ú•þf1ÚçÂv`稽ÏxÔcÓd"oÕ0➯ă)Âä¼ã’ñ"[:OÒáYt²ô,dâÆmod85w^ï ½Ù _.n÷ø”€YîŸP+±äYŠÙÞoÙc4É ó—Ñ5þD–|)’úy•¥,bïû÷ŸtŽÊ(‰ù1¹pyH¤åàœ™Å‘øªDtáZëþNë—ò^Ù჈hVôêÎiùü—ÄÄ©ýƒÍνÄÜÛ3vtGøvºÆyøørNM>ëÂáKÝÙŸã…Å"Œ¹êý¤îÇ\›—æ¾jy/R:‡Þp úU6ÚôNZÒm´ÌÈÓe†¼RÞbóž ¨Žý|îqÈ ”<ׯfmØíÝÂ+&ìÛ×NðoOHÀø»ì„V[4Ðr§W–R7-Þ2ؼ­èŽ¢ ŸÔ}D?%bêSmnþÎõ §PÁ’Ök[ÌA/Hü§%öTDüuzæ.\Z† †n™<TB=’!)3YùîçǺšUÙpËÛ~øžtÑ37ޝ¨çª»hÑQ»´Ô&ÿp0L°¬¤ C“‘<óºnÉ£Yxh'}Þ–K÷Š`åîxü+øDÔcþ\Í^­”òö/WñÙžâù~¼ˆ%RÎz>sl;µd±K¦Iµ¿,b´9uY€Ä ¤° iC¶ËÎT]çSïÂÏÃs"ërzæqð€ÆÁÁ§eEs)ùíë1Â.'q îŸFн—%î9^(O ¯q²Þ{ùs vi[˜‹T+S¥‹Û47¬„vR¥çû²Ð3}®JàbŽYô±ó†‹¾]"=ݶØfÊÅŸV0¬%.~JÐÊM7†uâs±ZUOþ6cÛ'ÌéÛãÒ=^Åží.ÇØ×`Ò«”yØîÚ¦}°È¨¸¿Z£Y,¨õ5t˜õ*$³h–«ò=ÝM{]™G£+H¼…Án06BZ†¨8Ëklܾ¾‘ÏÍ è$’[[{%(gʳm†ûÐŒÃ>N$ä,ô¹fƒÅ¤Þ䛹Ó"¢Ev¾þo£w¯ž°ó ø¾=%·FÄg;»x–D6íy•Lg=}£b>Qê¸ÖÁ«„ëõÏézˆ¨.„R¥¾iGVÞ¸sîÊt1PòÂõ¹ÌOfm•ÛZ©xJžnî¯ÔúåÓÎâ¯él±&DèÍyämî·‹Ý'/œ Í—Q­É8æ¸\Ó¶=LÛØ!Ô •¯åð“g£Ÿèÿ@Š yhñs–!u "Ù¹•§²ì—’XL¦ó`›túÅcrD¾5Fµ:‘fõ–öM·« ý ¹ô.–ö»ˆdè'}¼ÐL{žñö«v—²_ïÒ¥…¦}Ш4¦ëÈìŒ0\îP­_>ÚO ×+e܈5õf[xv?±N‘û˜ða•âïëpBHY¦£צXßD²5’…‡\E‘ÐÃÖÅ ¶Ý ”ò΄§›à bfñe@•ü„ÒªVÏ2T)eÇCPA‰ È>Þa­¡yáM‹’Ý5UŸüü‚Í/åSwÖ<‰NèÀ˜Û7ìŸcZKD¶ð´àB­­·ÓìšAcj•Õ3]‚;ó…$-ý[€ìÊ7Ò­RÁ®ã†<£Á,leÅjky%4¥EÄùלwôu»ä=<>àåk;|#Õ |ÖFrjд'µëœõ}çªÛé6öeDÚ¦ûÈ›ë¼÷y¹'Ùn}UApdlM²fá1ƒP†ƒÅÁs,ê1†ADŒ~ªû|¥G.y;¯ëï[Nˆ$ŸvPy…„‰ë`è¤ÆÍT”_­´_Ùoø:‹¢Ž”ø0ÍУY^T²Q6z¯}]wf¹.Œ›QˆÒ«ÁõØj–®qC´6¬ cÕ[´±sJP$è/|·Ë›D:Ü„÷zÌ'¤þÄ ÿ6žË±ÄÁÕå– •ýâ\¶áFFI!uƒþ›¢Ä <Úfdzmý˜•ÑÊ’߆ö_#‚Ê WÐÃx?yŽYüX˜lÉÂçð¾l5\Ü)˜öõËRúÙ‘¿¤a7·½6í˜KÞ¶I{‰ôU¢–ýxEFÔ¦%zhÅ,²c/Žï’‹"5£tîöëh¼àq¥è{|R' ÐkF#]KÂ}¾Õbi•\ñÃÃsùÕ]ë“ÜFU‹7Kj›îùЖxqrYA§|ø¿…V°l9-¾¤Þó¨§Ò7´è¥[l$L†>¹v˜çˆïuwÌø²µš,¬o=Tö“©Vܯ±ÏFöYP|¹Ã¨7Çfâ2ûüs7æ¡¥Ü1Ú”]ÏLSkvn!·á»¦EÃX“ð÷Ê õäp;VQ¹'~u[DNÀ¢¶EyØ„‘—üƒ ¤K³—¬Ï85›{½péí5× wrñ»‚ÖrS*Ù-™Í¡F¯íeÃf žÉæÇk¯=JÍå¾ä¹¤g Hù%Ì+A®’—ÈÍïä FÇ[\.׃Ò(æ. 7ãLWU}YBär×ä pÜ §y…u鬄x¯¾Š¿Þ²;‡]&k€ß´Õt)ʾ¤1¼$Í–*%äž2ä¤C-·HŽ*•Eö “2ì ËñŸÇ‘·É{m|$yó«3 µ™ ”0ðÓÙvB®j^&Cé(ÊzÌÛ±ÉTwÙgóã˜6»aú«ï‚@tžÌZj¥ÑVº97ámácm±zÓÃÕó»ª9¡yóö+WÙ¨šcWÈ™Ý/žÚ|½àr[cx—ãÄð°:ãbuúÊÑÃ&#¯¢cõPës#‰-ŽÒµ}:EË,l澦Üöf˜å4'wG/>בþxÖŽljF2"–&uæ8Ðà 7›õ[fî‚‘tšµ êoFÃ3öƒ‡‚:‘å‚ VL]¦çcF—[é›±~­ ÛÔŸ ð¢<­Þ:¸ò°svÍ~HõÄóUk]…¦ÄÅÆî{­ÐÒ•ó`RçÆ“ozÝ34ô“<ÈQŽð¦Ú¬¸ÅøÏæø‰}Ë?ÍyÊ<®¨8æ¸ç’ÏM¦òïk§+2éÑûG$iñÞúŒn'ô&¶æÊšöꥣ™ñ­‹rÌó“(<@õ ¼ÓדHQ·žS޾ˆ|V×7“ù˜…z{×ìå"¾çÌI/g@Õ§’̇ùÐéó<ëÖàøU%4*Fjß-qkw—G¡‰«D°Ì¹1 ¯¸ g×ÀO¸³—8;ŠÏ]­"æÆ0±SÂbQ‡“¬‚Óxû«ç½ÁÅkb’U³¹Ž&óÖ—äï®@‰<«öN%;Ãi·×RU4ðZ{·ˆ5Þ>AGf¨Ú\Z8GCõûLÕ}%;»?3‹EéÛ¼Æ u¯½aƽáÈàî¡•Wžpñ=Ab>¶µã=ºñ!²E!†¤O|,J¦R’•h—ý|½T#`mg–2›­)ÒTci)·õ´óÎÕõØ),Ê tYúgä-|"“¬…ç†l2¾5×éR €C+¥ŽÚ°@©º WÌÌÃ\bŠb¥íC¼ô Z娙`téœ—Ž¯æÉ{0XÈÒH“<_"‹é^SO€ÎÀ—Œ–kVBr/‹åßoæ¾jNr&åi7ÙY¤,У™oTê|íÛêÑ&ÜE决Y 5Ç ÖsgõaDÌ]Ü{…Â6”7Ÿìv}·‰²ýIÐ2£€¿”ÿm=â\òeè§£íV ÀR %(Kòž[`¶Mµ}è*­Ä͇dÞ? ¢”¡:ë–*F&¾nf|ï~06ÎÜLo<0ߟý¡Ëöª&£n~eæ,÷Ó½ö Ø£vÜ?©Ø-ö6Þ¤l¸äàâý·ÊÑwy®(63.;`<±)®‘)/ÕÅI‰;ð‰âclÙ¸&\Ï{¾I´.$r,hÚºTX¶‘SÃÜs–Lí•h7'¯`8üdíÛWžk endstream endobj 824 0 obj << /Length1 1422 /Length2 6470 /Length3 0 /Length 7439 /Filter /FlateDecode >> stream xÚtTÔk×/)ˆÒ #ÝÌÐ% Ò’ 0Ä 14HH£€ ÒÝÝ Ý H£‚HHIJÇ7ê9ïùÎ{ïZ÷®Yë?Ïîý{öo?L5u¸¤­á–8 ÁâŠdÕÔ”„@ 7È‹ÇĤ E8BþRã1éC\Ý p˜èÿru…€(òSƒÃÊîŽ$( ¼@ ÈߎpWQ€Øj Pã(Ãa7<&Y¸³·+ÔÖ*ó÷ÀjʼnˆqþH;A\¡V`@ Œ°ƒ8¡*Z:p+(áý¯¬âv„³(§§'7ØÉîj+ÁÆ ð„"ìÚ7ˆ«Äð 0@ìùƒŒ  kuû£×Û <Á®JᵂÀÜPî0kˆ+U £¤ Ðp†Àþ8«þqàüu77è?éþŠþ• û ¶²‚;9ƒaÞP˜-Àêh(¨r#¼œ0Ìú—#ØÑ ŽŠ{€¡Ž`K”ÃïÎÁi-ð/xnV®Pg„·ÔñDž_iP·,³–…;9A`7¼_ýÉA]!V¨k÷æù3YÜæû—`…YÛüaíîÌ£ƒº¸C”äþrA©ðþÑÙB °Ÿ0/â€xYÙñüJ¯ëí ùmýR£øû:Ã6(¨ õ‡çëö€®îßÿmø·„¬¡V€%Ä Ãû';J ±ù#£†ï õQÜ€¿~ÿ9™¢èe ‡9zÿãþ{¾<†22ò ÿÇ&#÷ør\¼@$¡þÿÎòücÿ­ÕCÿê øOB%˜ þÁ€º¼¿qxüE Ö¿V† ðïêp—!Ö¨oZ¡> ÿïøòãý¯,ÿ/êÿwC ¿Í¬¿íÿ‡ìuôþËEewj-Ôà¨å€ý·«äÏ*«A¬¡îNÿmUB€Që! ³EQœ ÄÏ äÿ£‡º)@½ ÖšP„•Ý"ý= T G( ¢ wƒþzqPQ@àÙP[gå€zUÜPûc»¡Vñ{¸¿djÉþ݇<Ì nýky`WW°7Š(Ià B­­5Äë7ß<Ü08@aöØÀ]ñ~ð@éþEc‚H^l€FާBÿS6ÁUFÇö[b_˧$2ŠlÆ“lȸµÔ^ƒm¬€ðŠ!§õWëî9b]öÛÅWiÒŸCji Ó,´FúÖ~ÔT}R>¦»¢Ä ºÓ[η/õîÑNî¡b+¦Â±§„ ·BóDç=~{w–ÎG7æqéìPÞÚHm?zÞ‘à§=æ]ÃÇÖ ÆÅÏ£»m‘Ÿ+'Ïó¢’l·ŸÝèZSHÖú³SFÊ\9|,`’œ¶ áŠÎVS›kξcþŠ´‰GDD;]»îžãMN×±µi0ÁÝÒë¥2y½^êëó Šç6ŸéÒ·Ù/ìOIËÎ_ãgF>·hfuxí&õ÷mœ‘bý÷¢ºˆvßÍ"‰÷nSs…¹"5_NÇ“´X˜ºrÍ^Þ/ª‹d)#^Ãty§KvwJõ§Ìk¦ÐJœè#Ù^›g_®ªx¦9€|ê aÔ£Š°Ñów@h¸_oÑ÷NC!:Mí\Q–=$;dâK]‘ñO;,¾–ògপ÷û*]¢Yôɇ~h›Üç§0zY®ô)š£ŠÔ À ’‰ÖÒf†—6†X—›¤¼¨[ò•któ çdã±Ê¾{ÿ§ºM›zöa+knpΰî:曥½ÛÕ³#‘Š¡8æS-œz²‡Ì7ëã4gW<æH^ ßK¾…À¢ÝáÏ ‘aDÜ,ÝñpáðQü»·&lâ_‰£üŠùå°DùWô/+»=]Ò53ܬº67Óà 2˜ä Kli4ü~øðº~¦ÕšYý(Ómua›<ùä]ü-•Ô7â[3Àí<ÿÚSÊuÞ· èK¥?.œÔB”Ñ„ôÐ=ìh†9ô,Ô—^ĉ?rñ[í;<,ˆ ÚåIŒ !&Ê !}£ry½-Üã=´5G¿Ð§—us—#µÿÍ‚hY[H@¶1©$ÚQšß “˜ø’ÏÂŒ-øõÎ>Ü. /EÔÀc¤vðými5!›}rÖ¤Vëæ««¢)Ϻ·Y!M‘Ñb58s š¤‚ŠÕj8¯œž>3¼ÑòÀ°v¹Ù’5.âH{g`JŸm‰E¥Y©_E)]ó0qýxG³„v)APÓ”Ê<|RßÚœf<мÄT-8ì5|ÿ¸ƒP•»@þ+Ä<[öÝ€«Õ‘ýƒ€³c#Aëjg8ƒÁU7yøöõñloy¶>;ÉÃ43®gŠv¦qç×jÝÖãÌ•ž6ð«uÏj̽Rê5²ë>ž=…ë#¿2Ag…},Þ‘Š÷‡µ†‘è,Sôïû²Ús«h½üÙqEÆàöãMS×·„ü$˜öØôLBD*¤Þk»cz#ã7$ëu¯z×½ONä·ß•F¼®[#Î :ï+l îcœfO±T Xò‡Šñ6û3ÐPPváaÊ’¹“™}´@›ÆÖ¯õ2çúŒµ”älÒ»wû*æ"ôþàÀ´C#áGùªW_¶1 šAc^;ǰsXʦaŽ}$‘d¥•Ìbé×ÌäŸÍ{˜”ûüêž1”­_…ü\^ *~Ü»”“˜FS¹íOC¡XÅ×ûY޶?˜oæ=+ó÷"B§üÂd ¨Ù²_&ç]FŒÎ ¦xø“æóóÊDH`ôN޹”2<ÿ&^Væ5Êo1$ ïËr¬èx£=§~g6‚ê{]·â5y'W>2,©åD?}Ò• º(Ë€Ý V„H›.ûºþRÎ>´L‹™Ú¶ízC¹Xø†_U–ûÀMT¤ÖÜŠŽû¦‚1FY'¥(NÝ.ûëU~Ÿõ|ÿ[Œ¤“CYÎHF’X:º}ʶûã" c=LÔÒkï—ƒ¿„w4.O5T9¬Ie}- GÜÞ㘊)ˆ‰,yÞqDðÍŒ¿…“"yŒ>„!ö¸®ígÞ°®‹R»,#{•0еëÝpÓÃrAÊPý\©Fµ+' ø6í–@²ÆR-óÞ{¨L˧©‘¨ñN†N–Þ·e`érË!@àõÃ[|ÞMBštIƒò¾1Ræ±µYw›ŠÊ,fÖãZí™s“ì\'"Ûä©b´¡EèýZx„žMÁªLöâ_m0'9“gÅhöe‚5Ÿ å?™â—~!ŠäSz–¢G‚9}&¹óô“5…æë{Ë)×ðÀê‹Z³W$Q"g`µ¶†›åØ2â®Õ©Ã-Ž'·uÑâõ à[== ̶þPî¦ø(¿Ei³fy(º¬æõp[ˆ"xɨ/Ï ¸)Ž5®’;ڻì‚#6oº®,ZˆYm¥¦íjx²ÛãD§>¯S†#Úh€-Þ=%E( ¿ˆÝŽšQKμ„²ÈüäkD´dE´Xn¸r`—4Ó±|ÒˆOž½’÷ˆ:¯åÆ“M8›˜îcÿÐäýZOsÙl*õXÑÉu£ç‘LÖ4™“a ki$ š‚{Gåg"#Ú•%Óv¦=\Üï‘úI7Ì6ù4÷«¯ËU’ Q›‘^žŒ*5c<Í|»±¤Äí®]~a‘X1›øn+¯½ŠVå~«ï¬DîÌ,d,â²H¤Wúq}U§Ÿˆ«Æk î‰=t²¢Ñ•]} ¼ö«²™çYQˆu->ÇM ÔÖ÷¸zmv|„µ_~ýdį§ˆ+ÁyÎëéîõf á«tœIœhÛŸ9rÇêBdøÙþgæõX CcþÛ&ézY…²”D#§w¡f÷v¤^r“äϹÍ4ÇíIPÛ<6¥™›U&Êœü(ûàéu¥;eóæ´y̤·llk¹Û<ù7üîÊæÈê %]j"…Ñ@åÝvÈðá÷WÌ\ÕFýÌq&Šê»=ŸÈw=NXRïEן!£ñ—Ú¥ƒç„RsL+¡³D|#ܯá‘Õµo*Ó}¼-‰3t³5‹øÃ ‹ê.4¢õç,5éþ˜G|7X›‡S¬ë« ’™Eºç]›>SÚöÒžgîå`a„úP¥KÖöAAp.ãô/o^¾ÖÑHû A–½%õº¬#º®…zÕ›ˆÖ´«Ð[2‚“Øý‚-ÊLA%(Ð_™ûìƒí¿áÒ¨=á›#†gp?Ÿ¬3µN <#Œ•UBu^ACó:ÌYó³–kl´4e`ÎÁÔEæ9sÞ Òˆòëw & šº&þ,Í}[ý ²>é±ñ=Ö¦Ïdï±iܲs¿ÃpjE‡œÍI’z…L$­È×%Ô=(3î@ï^‰wÒ¨,Á¼L)|p—RÇêílÔ1Õ£!ÿ¹ 5'9½ÄV»©M•›Cßþ.›æ .#‘b»1ùƪí’"ùU÷¾¹Ýû%»*ôƒW‡Iá­Ÿ^ÓÖ‡ÊÖU9Ž—ÁP,f`Û^r]ÒÎýؽJ£¸ƒóÐßI i¹ïœa¿°ëÕhÀ¦©àˆ]ž#3'ÜÐ!äþëÅ~ë;\nßj_[lb™LF³ôÝlï¶=^Q¨žH±©–iœ±™íùTÀʆVS‘B¯õj™ÉrBвׅ#ÞL³APúê;]qÿ2Vˆ¦èSV,lû ŠìÊþ`z í…)óŒ:Á`oóS´cš´|Üm_µ%a:9öjmγU&®’›r"í™/3æãÙš>½Z#kKX.w¦ÔØô€v³ ò­SüjG•ØŒWeÁ!ÓÕíìbb/õ7Òúršöˆp­:éÊX"Ýyá)ð~ÄÛ1\übJù™¦Ð5s«rl혩¼êÄ}Ž _RõèXW½ýÖ‡äÑrNHæù¨¯h«Œà™]¦ÎnxQø‘o˜Z×|åðÛÑÃs?–&ï,'<Ãxoâ[ݼ-Çå¬1(3ÑúÙ?åƒ Í퀳ÞýÜÕò;<÷›¦Å¼sßä\÷L@ú(¨&{3%o¼TÝ;·-W_HoÉ£¸„aS’aå·©Pž0lµ—œϘwˆ’D<5«bÃ^Ñ!"hzÆPT+mÇVµ%þ°Üd†"šjÝ$‡9~!QÇ£ù䆉Z%Ik+j…°žP…sý_äcÛô+2E\¹A ‘·ëІرXbarSåÄÕц7§üòÁùò´þeï‡å€H‚ÑÓÞ#œ‹U ®OPfÇ;ˆGPD,ã\õØMè]jÊ,ò)Îÿõƒjñå ãñUFoÚþŒ…"Žh6Öxl/ ÊÏÕ ÍžëO³mˆ²ÈLD*2.¿•þ"„G-Y6C<ìÙ²ðó2H+ÄaEc@÷<û§%«àx„伕ù˜}öžéb›þ´Ý®ì`Ö+ó~³â—t¢¾£’ù·2z—8³8ÌYÍèwÖ>ŸLÝÜQìqÑã=<çÚD%Yå¶ZïËÕßË¥’]{¯}&ࡲ.Õÿòø¢q㼩¶JÌå aü#BÜuDÜ•“ò(i×þyUמž­‘KkÈÚîFlŒN'MbíÒ¾Á(©¸ÍôT£udW"ÏP%Fu—¾WB¤‚12Vôó~™Ø·€;)‹8…ÕZ÷ ÉÓø§¾ÒŒÔb×fgœ²*½ê\˜Ç'êR Ÿ»Ïד¸{¤91B ïŸÍx£Üäýf£ÛL-ïÜb±âxJ*ö Ô2·æ¡KK´ƒ7Bµ|ÇÒͰŠ0 jž«Hv0Àó(Žò~Jaa?™jô¿‹G.Žžya·bä‡î\œL£2°É©éµàlAœµ'ï—–æýÈAK[¼KtÿZñmÌpÓ‘–hÎà;ZÒûß3?ä¾€VVTD{q8ž\±ÏEl…ž>À/©­âû6Çe w̯ìÏæ½„²ø¨u¥Jîâž;ôšÝÔˆýhažÑóÃSò’’gu¾±©ìŸC»£ ñ«ÓóI“Ö‚‚9—”»‹"4.´kK^5äµ–ó‰>ˆÒPŠ´g,r7ïØ£ëó}˪7r:`pghŠRµøÔ ^ ],q Å£•v¸Uâ§Ø­/R%ß§lv°Òp9{I,L]À̦´°/_šù2ωõI¡1?¿KC€Ë³GîCk@Msž×óÛ’ ôîȦÝÐú¶\1©—µ€Š±é¹õŒ¨ÄHzKAVõ˜[k}fè õׇLìL%¤9œÜkÑ…Ãúñp›“P+n±ÜÎ?£îÑ€Ïy¢+œ™6 3oï²»ÓSªØ &s®^åSG’ ö~ÉÓ’°·9Ö&*øùP·ó‡êÆnoÁA-É”/®]/F},kçzQ ’¢ž—isØÌMõÚ^㫌ÅvBÙw·%©ÿN‹”aY¡¸°|Â&žþXj€]p‘;Ï™„GÈ%p!ŽSáâãúþ͆9e+ó€z ç([ü«­ô§ýeƒ‹Â-æúBÈRò!ûÃñÁ©æ¾s™%—"Òüe×ápmû ©ppÄ>'CªÉáÓò‘9^øÚ§' \åÁÝl¼óO{°7ñM` ¹9§£âæ‹>#¬ÜVbÃß¼½a£OŸÈ¯#[;!AúñÝk†pÛÖ®Ÿ‚|\)½Ä83Ð ­$ š‹XFª‰DfÎÕòÜÒ;2^“µRÞœüch ìì­šF¼w‹WÒSÊÇN¼Wlçt%JŽÏόˉ ‘¾r MÙ¾¤J¹Ç5 jØ÷&{¶yÒþKZÊÍ&Y8ý ?“¯ì¶/Æ‘mo±&etFŒX7KÞ\ƒ[Q]O!y~0ÑÓñæP=E•ƒÇ±‰ø›ÖðN™K»!é,^õ^ªçñĨ™Á¶gÏÕ~±–œ)ej÷s)áç¬ ô7Ï&¯õÒÉ:ߪУO ÈéÞáA“’ݺ>sTà´ß¯0¤Ô²ñ’ýÖúÆPôÞQÓGÇÀ7ƒ-.Ãó7;°¬H<ê­öÆð¡¸uGÙøŽ #as£•qoLr²Ð?Ü 4òÆ&£ìïó_ó¶½ïi\õê“`Œ[N–€vç1MEüs.ñî…ñžO•ÄéJ“”å䵎 ß”ó‘TMÄÑ’»ÿìEÄ{µÍ•ð³sá^š^z‡[YÕ©X¼s—ô…ãÈÌØG㎤ i[Ù8"äH™@5û6à÷[|“e •'Û0yªæ Ým·Bãºz’Ñ…Œ4¸ÕêKÓIûn¹ïÃÄîø÷x5´BÆÀTÇöV:ÉÖ …µçpcÓ]úÎýmÿøº îר¢Û¡{ì»ä¤uÞ@üíÿÉÛ»wnŠäL9Q‘­ß–“ÌäEwÕœ u„húÑÐô˜ËiHÖ R1wëìVϺl^ÄEž·=”rê­q‡WvD‚¸ +l×"¤ö37¾:h)Nª“è·îh]t¼ëY £¯©5–)û;Ó:ô?hÙæà É£€nê¬vèØ_H‰Ì¤˜|¶%=ZLRŽ¸Ø“˜¡x+Aö ÿr,—¼7WU7#å3‡•ê2Åûaî¼êebÇT’ˆ¯þ©C'¯×ÉP}4µÀ}ÙÇŸwgf—xñòebÈ<µ¯Jn(:™/+8+˜¶˜vè¿K«þP«ŠsÚÄ7Hñ}#|ÞÉ–ZÁ¨'Iâ³?k7kØŠïû±íµ©&×®CSsº$Ñ»´w:?vƒÆéCÛùïàÜÓQÇoÒÒrϨ¼·¼§í‚æöêO+àLm°ˆëdD¨ïO+ÿm“'Kùë ÿÑ-|¸ÅÈkjöu ù–tÙQ¦¹f~•€Ëñ2sœê^c#²³s\²ã(~}šùîA±`Ä!¼Î%%¨"f=/#È&8íixMjæ‘ÞÕüˆŸáÃÃã˜(Ëù^³âh}ÏN„°<¤yÂÂ`pΦ(Et’ú±kvÌ*ˆçNm¹Ï&Ç·p1`Ê|Ïa¨#®×bIÒ…Ít5ÀÖ¨0ÝÜÔ·zƒ×çb»(gîÙÖº—\{óჾÔ/¥FÕlÇJÊ…‚YýW+ÉâeøZ<¬[…ôï¿ÒÛP½Ó’Ð}µP°<œT,e4ÏHHuçñþ)ä…{QøM7O]q'rÞ–H¡ ÂÖã¾Á”™Å3và1R…êýÏq R¡v9;'>ñÅì[24W‹¬ÕN3ˆM‹ÏKCï,»Ýóò·º¸ßŒç_ƒ1ÐÐÒi©ÁÍVof¼ a®4¶glŸàsõýf¼¼^ƒxÓpŠQÜuO{ëã}½í€ÀU®H=ELté§óTƒìA$YÐ&W³–Á;¢Gc›Dc3Z„c?"½µŸšÊçœÇLïTYs¸æ›u*Žè°CTë7ÐÚéÞÃÔ #©›h˜ ¨§ã¹U(]¿Ökm4›N0däËg “f†ö×ÿhttƬñzJloPœ 7Û üáœ1­VŠs}Lþ|è¼H¿?C¤ÝXD'º|Z¬‚[D”¥ž¸òåT`ÄIP×ÐÙ6x‚“ÿŠ©‘˜IÃý¥m{Ávz¨ÏË_5þ6@jÑp¦u¼D’öÂØ ¦þÄÇ930aæ´°_·Âã®oưu÷N6s„Ë«:”£;ª ÂöËÜÿœD6C†cÄCp•iܲ #d5²¢î½>ëÿ;èk[ endstream endobj 826 0 obj << /Length1 2894 /Length2 24747 /Length3 0 /Length 26360 /Filter /FlateDecode >> stream xÚŒ÷P]YÓ ãÁÝõàÜ5¸»»ÃÁ‚»w'8 ‡`ÁÝ4¸»»;Ü“™y'™ïÿ«î-ª`?ݽºŸ¶µ7”¤Jª Âfö&@ {;Ff^€¨¼ 3€™™‘™™ž’RÍÊÅøžRèäleoÇû‡¨ÐØ$3vÙÉÛÛd\m,lN^.^ff+33Ïÿ íxbÆnVfyF€Œ½ÐžRÔÞÁÓÉÊÂÒæSZ ý_Ƕ@'+Sc;€¼±‹%ÐÑÔØ jojtñü ~K^&&wwwFc[gF{' Zz€»•‹%@è trš~% P0¶þ#<%@ÍÒÊùo¹ª½¹‹»±ØX™íœA'\íÌ€NPp€ª´@Ñh÷·±Üßô€j`adù×Ý?§9²²ûë°±©©½­ƒ±§•ÀÜÊP”ctñp¡Û™ý24¶q¶7v3¶²16üÅÜ !¬ 0%øOzΦNV.ÎŒÎV6¿RdúåTeq;3Q{[[ ‹3ü/~bVN@SPÙ=™þîì{;{w;•™ù¯$Ì\˜Ôí¬]Òbÿ˜€Dð¿e@333èz˜Z2ýr¯æéüKÉòK ÊÀ×ÛÁÞ`Jèkeý÷v6v\œ\¾Þ*þ‹àYXfV¦. …•üoï 1Ðüo j¾“•@—4{,æ_?ÿ>éƒÆËÌÞÎÆó·ù_ýeWSR¦û;ãu""öovf+3€å×q|ÿëæßü/ù¿¤JÆVÿûã´¹=€çï@Åû_nÿŒÍ?+C øo{Ð,4¿G_™ƒÙô‹åÿóüuäÿßÜÿòòÿ6úÿ—„«Í_jš¿ôÿ?jc[+Ï @£ìêZ y{ÐrØý_SMàß«,4³rµý¿ZicÐzÛYØü[F+g + ™’•‹©åß3ô¿.€ÜÛXÙ•ì­~]6PÃþ´p¦ïAŠ3¨W©€ }úoHq;S{³_‹ÇÊÁ 0vr2ö„µ„8Þ,  5zü5Ú&F;{Ð(=_€¹½ü¯Žrr˜„‰þFœ&‘߈ À$úq˜Ä~#Ðþ‹¸˜L¿ €Iò7b0IýFl&é߈À$ó¸ÈþF .r¿ˆ‹üoâ¢ð¸(þ‹¸A\”~#åßÄEå7qQý@\Ô~#õßÄEã7qÑü@\´~#툋Îo:gü/bY›‚Fí_ È“±­h¹~]›ÿ“²ƒ8;ƒ&ÒÊùýoW S“ß”¤‰“±é{ èÅfîò[Îö¯üï5üWŠmú27µr2uµ5·MËÿÄ ¦ö6 Éü—Ê/CÐMüG ‘eúÍ•…”¢™Ð è ºõøýN4§LÀÿÐaa9Úš;[þ!‘ûŸ2Î_~]A—Ä¿%ûeäajclûG4PÁÌCÐó? û/hõGþ 9Ø~A·ßdY~ ~ÇãøenïêôG4Åoª™…“ñŸ˜A§Àš+KOK Ý ÙŒ˜Aõ±þ‚JúþŠ`óuòÜA¯¦ßž9@Gí@×ÈzP5ì“¶ÿ”žÃo5È™è›Áî?CÅÎòô¿#ÅŠ]зÁ¦œɬìÿ˜fP¹l\ÿŽ_vüÝâ_Èèü×øï€²þÚ»ÍLlþÃ…ý·âÿÐáùGó_1˯þÿÑ=PésárÚZýwê9~ÙÝþèȉ³ÕïMaåîlóŸée¥þ;,è½Çäbéüc @µuq·ÿãȇëÔf·? ˆ™ûC :íñ¹÷ü‚Êåõ›È“ÐéïPÿyw˜º:Úèò×Û´iÿÃ}Á@Søù{S¾`ëšàÖ»¯Âî Û£ï&)·5Óh¼çÚ\ß$ÓVe®:Ý'u£.mŠÓ\ -<{6Õ½ kNRnyôy2LP™ØnŸÇî+8®í#‚#dPÚñyvôÑxÙÞ!C™ëèʬ”qçÞ+éQÛWº8:³­¼SÅ)‹ðTú“!F=Z/ hŠ2Ï${— Æ…ö-ú™ÊÔõÍ$zÎØ+‰L¼ïQ [¡·Îkìý´×r¹«s'ž.ä5úð•·È^Š Î¬wqáRÿœG!I}ê*ãkf••J”]COµÛð|;ËVn2 ˜š c+©º¤ÓЉL«ªÅ0 Ã¥ší=h¯Ý\d¹õF£ËÜ:•pçgí+` IÛòп±Ëû±Îqyè{?ÃmhjóÝPÃ÷Í._Í"Á>AB w–·â–º‘K‹¼™D©Ð¥.#š@iLTú·dî'hã~ïÀs‘|–ffnèðaÂŽ\ŸóXߊú3…öµ)´Ywtý × N…W“ŽÔ³³~"€—céÖý”vµYø–4Ú°é¯ü-û¶§u ÷sY+C–g+¹Á«ûþ°õõ_¿f á ^r¥b#çBë&·_r{(ñ³³L]¾s»“[@AâãLojôu’ueÙg{ÌPƒ¶ÊÀ®“r©¨™˜ô½ñÄ%žyñ3%¦Ô[u<õ×knÞaWdw#ÕÍ4¼•nÎÿzZ[õ„Õ¿c…ϼJTv!/s/Ÿ£Í\>çæÍ¹ŠûqFï®á”ã8”AƆ÷îòc¶ÚOmYÆ%Y܃!Ú.zÉï²ÞÆá¢:"’ŸÚà‰‰<i#e©C{X™'5R+9¥•((l÷Ê’pÖt;q§€#CQwø°x²Ã³T¬”Mª¼Âne†ñÒé]íýäËY{q½V\Ósæ8ßf´¼ý‚Ô×T6ñÊÓ1Z¼*ØûYö#¶)-î±Ûu½3‹— *Á’ÍØ±Þ«G;µC÷¶¤VŠ\3=ÑÆÌ‚ÑÅ›™1¡BMV’=nGR9³Ÿ•›ö‡~[,Lу"¯ŽI™»´óì½î)ŽïÇoü){+:&†°Ü×WÖYõíK{V•†Ï‚Ò–?P\÷òDlO$`pxëYaçRÌ`K=9o;VDHÅÁ¸rvªîT% ‡“_«>IzÝóྤNÜ¢~n•~²Tx¨›ñÞRD §±@ʹ™NÛbA[Õé¤$“?:°íjМ­À-¨°]2¡džOƒ~û`”qø¦7/i5‰Éüº'Û¦RIœ5—XC˜VUDŽi‡¿û„£Tô“ðçÕÛl¾Jï4äÍsZÐv0‰d°Q`i`ÁÜÞ*sö‰h]½j84[†šg&Â/d}ìå 1f&S5ÑV_Ú<·ä÷^9ýËr« Ún]>‘À )²æ1eƒIœ“|üÆæILž¾iŠ"/?;.Ù§ó¼¬ i[þÚì5-ñݦô¾Œ¬[F 5§!§)B軫Aµ¤:¸h…GŸw°Rtª‚ŽÝˆ]ØÖ"3YÚ¦”͸×&5áïqõ×PwTK# gàòJ9· IMéõÚ-(÷ø>Ñáe?ÈéƒeÒCc’+öy|p´7>ì-Pùv&ÞPȇ“ _jUÉØm O}ËðkÎf¿N ñÛÒ­ôª8yºÿP>ïåÒa¸€ e6ì= ¾¹¼Ö‘ðId$ôJEFÅOkVô­ÜÜe3ÄAG=¡!9ïôÞ­ ‘I¬=ÈJÜ©å™<¦%´kÄÚÐØXTve/˜ü¬ˆY&mÜ+N™þ¡·þ|ô̮óuØPƳá¨QØX4\Ht6xœïl›i‡ì•Ðû¦âónï ¡Ü'/<ýX´³R'„ÈÂüÒ 7±ö(yI. i9«ª$á9 ‚u;NOð0¸8 Åú ~Y¸íC¥‘ÅXaaÜïn¡IV~ÚäSíÖßioÏÖQÏ‚i.ŒoQuæ3È^ð°2˜¬à¬æºÂ™|Âï…çèõ–*œÎa‡÷d¼ÐÍõhÚXvav­(ÍFtcÔeÿ¬:Çjâþ‘ÎàRRp¢Äǵ$®YFè#K'%öÛ*ã£ãrÐ+p÷ÀC×Þ„7Xæ¯YÚKÂB'Ì1\jJ‘¬¿]?Û÷§!F´iÀ˜8a1Zâve¼t¥;Ùœ'{¸à;£ÿà5T7A oßRµšë9Èœæˆ63ˆ‡®É"á1v2µ—º °x±Mˆ©÷Ðð¼®_@›È&Ó'÷òÃM-rp»èBÊ& MH¿™ë+ftበÀ²kÔ­eyèu)5"¿-æ¯6%ûs¤ëT˜ù4¨}݇q¬íôm­ž#D,ŒºÓSz¸‚•WÏ?º|‰>›” êœF‘Ц®©×QE‘ž_s¡ü¼õš’Õ©[LËÕKÕþ”k9j—X·¯M=µhÜýM­çœZËéÃÔj:“¡]2¤Œ\6,MŠ|Ínîñ øŠz"oY‰úÕÅ3ƒ÷™&+Ýv~ØÇFrUŸõa ÔóÀ›ú¼ŸÂÑÝ6NåV—šwòÙ“®XÒ(>`8Ù ¿ž8'cv÷_^Øé¬B¾MoyWrûÝùúÌ>ÓDÈ;Ás–TT”$ÊÇ–QóƒÎ·£Sâf;„5‡ g¥43 † ½›ªÑ©L*9~‡(ôF DŸ&¿Ì:î½ơޔotæ£^žÅnA$ë†5"^•ßÃrB¯XݦZaa .[¯gÃz´À?“rãMØÂ§,†áZ¸Ï“¾‡½ãÚ–€ÓòTÕ÷;ÉH¯¸·±™Ù/O‚#IÉv#e¾ßkˆ”øˆ¸¼úpR"¾j¬h~§äÁî/’‹åsðFó©ŽoQ’xUƒŒMäŠcþòiçn]Jl²LæŽ%e4ýØ”CᎧÔA€•K¦Eäù²Þ™ ò$ò›ÍU‰–2=²‹€nå÷H’¤s_c/‰ >'&Uøƒ­g%­U=^¤Ûоu÷fq”\¯Šˆ‘Šˆ±MÇ¡G­aî¬v6o ‡|QÔêÎÉ"æiäŒØ– ”z‚ÅLÖ!k}óy¤¾+FOŨ4 ýK·f”µš(`¤V‹vQ†]¤ *Zá> N3Îkž ÍÙa•9¥ ^Ù-tÃ"µ+>mº+@3È!Ù¥D¥ B®`†,Z`&Öû}Âîã‹1"þ:~\,+¶rÆ ìýÖµDR•Ð/ðqϦCÙ!!¿,ÿÃ$mgè·ìûú ¦¾7ªxÔˆM×¼[.P2ÕÖB˜eµAâ4Ì’ßùF›±•!bK>¾W£n:û„Ê÷‰?Þ‘ÀnnË5ÀÅFN”%I«À1‚Ÿ ï˜0Ûëø³0@p+jÜ‹ET•®“ð³K1pB•u­L&E~á{p² Íùd=,q3pHy›ÉÖAC– \óéCÛ³8·b)•R±¦Ó4YÅî£îÛÑ×»ÛsU ƒ©˜ ý‘¢|tvO:. ;¥½]<™ƒ'K¹gZ(^ÕxDü˜ùNd~XZŸÀ_†å@~9ÙŒf‰<¬«*gYªÍ°è§êôâiÌWÒ–,™ç#æŠ!Ô‡*™ÀÑÃŽ âðO\^ Á‡¿ËJ@Èî j“²ËGÝtÆr ôXJßaìXŸ©ªÊ{ŸZ¹`ÓËG•REο»ñõOk>±%á•iÔ0Ð ˜¿)m &¤*E•Âÿ Ýšxt³ãÆÈ–$ÔÛÔ¨.eë»4®&õôlÝä=Ÿ¤ÃüdJúÙã :%ÐdLþe&bÉÜ—m5%óðÇ—M2É’´Š]jsyç‰7S$ZšêϾO7õ Ú½õ1þS³”Ö#¤Rí§QŠR¯°C#±$†÷ߢøöÂjF/>$lÈ4ºå!×è/‘ÃSÌ¿)EY¤µ àHçVÅ}&j9þñµë\(©7.ø¼ÎŸ3]øƒidè¾½&x<ÍEŒXCù¢Ñ츶·õ¢› „Q¥Q3µ´Mîó‡µjÒíº§¼ëI¥îïGÞóaÄ«ÒNß:ï ÌY*¾‡4Ên8ÉÜt¸{@¬àvõ\¢pºHY¾Lv…7÷5uì¡ãèòô#}^ÖŸÎ~ ¸ëÛýzƒoU’®†’™oîêçY¾<¢¸0EO!¼¬Å oœÁ¯±GT³TØ…>Š ø:ÀÐ혗ZðXR=÷ë ÊßÍül’”½áã(ƒ)p8lÚ’vr<.f3\ÕF³r-÷ï^Þê¹h›8=ú‰®í„ºO$v}ó`FüF¥r$삆xÈPOI»Ñl\Z0Ôl¹1Æ£;Uäú «º‹Ë#›ˆŒÖ«&[b¬E±ån1”ôM1HwÂ#ŠÀq è³'”4MÊk«5*‡\Q©t§i½¯%q'E‚—؆úXw¼{‹v ]Ûs¹ïèénïXA_KÇE½Í‡y`'Á¸‘ë¾Tù ÖÌRø^]F¿Á'Á Ó'ωG#ã³<ô/ƒH‘ºU£‘¨F?Û‡Å?}îvÇï‚>2&&@ÌóÚ±º3ÆA÷µþþuwHèñsä¶oß”SÍoÐoÒ·íœcÓ˜íÞ"{#WÙê”x]F%GhÜå>&q`› üüy*k$0ª+¦ì6JÉ?Yîr.lvûÑÒo ÷ñ6kæYùûz±‚‰yÝbkûJð'{2¸˜ù"u¸V¯‰K‹‹ã­Øx×:‰Ü‰tþ ­ÏåÆÒòqˆ‡·­ƒ7¯ì‚Z¬úÝñìÅR#ù™³]ãŽr@ûš¬4õãK?ÄÛÂÄÄq.#Úþ‚Ët)»øOÍÅÂ\dûÞb¡*üL¬.Ïò}W÷ÎÛ_üßóHk]%š.Éš€Üx{~¤Ã˜ÿ¢%~T”‚:Èx°NÚ9ÞCöVfQ• ¹sA›¸ –púÔz‰ˆêç¼ðž "]ÙNxGS ,úú»ë…¼m N·U|5m´òEÜJ¹ÔWöÑ¢“]ÁL°1ꛣ۞û8f’r3ôt»ØÎXå’/kL%Žu=PC7à–Ñ}(å÷÷:Äå^Áb%.Bˆl·@ôŒÌœ=ù9!kZ~MK£-ùÖp×Ùü¡W¿uàÚ±†˜Ì´Ojs³ŠïD‘¨Sä N¿Ú ðà‚9î3DÚçÄJ¾|Бd“­²7“ä£ j¹ È·z»øÏ·SIDø|ép>*1½Þ@$)×)ÎWå¾çñ4êle¶A>òÆX¶KÕaÞRk´ãEÊF™„7Lßó_O²ˆœ4Vºñ<ô¿6Á´ ÐnœætÕëûÛdßCrØ·£êîæKð¡Ò+PScX•DêU+(wI_HM\“t ªñ ÍIœâì*¼"¼QÕêZf®æ/§m±\Óœ hc7o’k°Œ[dœ«Uƒ 5P…ž` ±s÷}¦G×QhÇ¿ªºEÐFˆQÖ{uOÝœ±µþÔƒÿ6çrüò¢½Îa‡#ág˜éÑ©þÉ'ŠZ+±~ ,XRE}•SA$=xwéFà‰wHÃðbH`ú Ï[if_ìÉz=2ï9,ØS6õ¯þó!×-‰,sÈáù‚k¥Õâï´âñáÜ(Oê…Yî´•g‘?°§x×Ì¬É ›ª–°Â-ß8 fµ:Û#14 %ÂËBJrÅm’Uø(‡Aì”>lt.¼œ}B}?÷ÊMשbDòú›—NÛ¶u ³ÆÍœ©"°ö¾ÃK˜Ñ­5k˜Kz’ÉÒ[ªÅ&® ¼À6=ZÀõºGñùáÒnÍ2ÑŸ)¼ëô‰UÙ9Qù‚7,ãÖM/KâwQ2–¬±ŸŸö”©\§»´Â¯Þ¥ÅK¸°(hJwC¹V w¬Ð²$¢ÊÁzÔU Sú‰¬g¦7«ÖbOm¿uyËÀ¤D³f‘¦æ- Ú¦ün+2:i3ÄSÔ©¢GÛ«¿0” Ç)•OØLZ”Àˆ)<ÀžÁÎé¥÷Ãæeø92K–ÿíH€,Þì²f¡ê¶RÔH¥p©$uP/vïÒNíøÏañSÖ¹q)%®.œ*âcí-Í!†‰!tqù„YýŒA‘ˆ t0ýsVJ~å¦ ¿HKƒuâÍýᣯ>/ x›}qpŸ&³z°: ±‡åqJQ÷¶óúáË©ªùNÉpó; ¢^ Ъ¬æ \¨ ¢[y«h_ð¬©ÈYÊhÖ¿^/Dº;›º'l€_‰³+‹P¹$ÚÀGé²4<Ò½£Jרم¤Ûˆ‘@:D|?*%Bn2É Oâ'y Î[J<˜¥úS¢«ójËÌþîÞ²OlÎ\´AŠMÙnc~Ø‹~ÙR[” î[_˜UŽÏËË%p¿Îe5(‚œ!м2|¸*|£tF$Æð$K¦%)@t(%š‚PÊú4ÿì¤~zxâer¡&… JmSȺ±€ÁÈF9Z‰[³ƒFxÀ-º! B§öíp[[ýÖÔ¯'•ý»¢Ú@¨‰‚l–—+ŠyÍz*w4šÀ†¡è„ÖE0d™†kÏv!Ù|;úŽì\ª%¯)€ìpsÒíÍ}LÉÈÖ²ˆˆÃ™sŒÀa“9bR²ÚXvÇpJ=–žkÚÌ,æ„ñ:k/ª:D¸ï€{pÊD*RF‚þÛ¸/VöÓÛ›9vŠsÖE‰j˜²Cwþ9£â5.Zäò2ÞyDæ\LéñËÓ9 ó¦´ªeŽöÓ5½½c—?wHß[©–â>¿`nÔ°id¾bÍhCDmº‰ïð˜îsy¬>‚¾lOw=QWë|?õ6Û¢Ûz+v©f–ìÎêmlí.ˆTøSÇ{mÏÃ7ÝøàÂ!7Ç—?ð¸Ì~d6IL|±¿½ôc Ñmx9Þ,¸‚sHµ ¬P߈¶”ýÀÇž¦R°ï'§/h•Zù"Éåà¢ë.–^]‰ÿÃ/Ž6È|YšÀ¾Ú£¦ñ®¸rìz “xèýbÃ-úhRùFìFÇîWýÛ&e„×|#ójJ—êE,íº„La{'XÁa“+DÂì)à6»ùó©Œ tݦQ¦iþÛUMùíð¹ +©ˆì‹aYÎá8ìuF”<õGfíl%ÝK™u±·+Ù²DsňŠ;ƒwócîf[LF.î¦Ê*Š,;çÚ•rUv+3'ùîš³´}Þ'yQÓ}3ó×±nïo¦Øý5Ü’…å?¡€-!Æõ‘nÍ&ÛC…ˆr3Qù8ìqCiBlmU/ IÎ'Òc3ŸÊúMSË#ˆ)ŸD)ã²3M¡§-€ 5Û‹ÿÐÁ¸z~«‹JT;ô\ïútø#¤ Âf× Jmn¡Š`ôÌÖ-6£àæ€ß@m~Ï¢†zl[œ'½túâA +F²bž-,1V@l‚Î7“¸Ü™Î­8"-ÞVÝU¡ÛÑ“Õ.îí¼`òˆ‘%loïkz¹Í&3ƒðÃ?Úø¤r DܼE¨Œ'æÀ§š ÏF¿EìWŽvS ãá÷è(|ÂLñ9¯Ëña¦×&£C;ŽS¾©'®Wn[M#65K¾Ô[ŽXÀ¾_àÀMNÒŸÙîEº»í È|dk¡81#pM`Š{Öø“žžbø2©Uu6ßÀD$.Ì4ηòÁ-x™ïªimÀùø¹KÊ{JÝ9Xê=AVjkŸëÔß¼dJ#ÝP³Žj3ýÌÉòô{2»´x%e´‰.Àid3òâeY wÒ½1‰`+C›Ï°ÜHY€Ï *À¼ÝÚ9N^º]þ†ã(}ÖOAŸíB¿! /ýˆ7˜cÛÈ?_Ç-£=,Œx ú®„²ÈV]A-ò¿ïÁ=ÕÄOÁ¿Ý]A舽ò»ßèXv.Šáþôµxi—âÛë·'hD3ª5å5±+”ŸcgcÚ6ÝxøäT3RÁ(Œ?¬`Ëžölú¿¯7,M"uÅÍævæàíw2·Ó–÷f¨  ÚÚŠ>Ò„âEÜxçá™lþðˆÔ=Wpblj˜UÝåp¼|$l¹Œ·EvØCbȉO‹h1d…‘Ùñ·¬¦)!kB_{×VÅjÆîjÖî™—û À^Æ]_Û6TÍ §r{¶"K“Ǹösläj[=å=¼ /qçÁaã)ñÂÝb5E€úÍø©;±ÍD'£D&²ŸÙÏPªþ9—’^_ êê |B— ƒkÒ pÜCŸßÜ 3<×4mÑH¦©%”F%\\TqîT¼¥ÌPÍY÷ÝÇJƒHš®íº*ÆFŒj×=¤“¨Ãv%ØAK^íÑX'æ‡w ç»3!¶q ébÂ+äíA“g/þᆼPnëñ<ƒÜ§Ý«ìW¦œË‹x<´wqz£Ù(ñô p†vgñNDýøÓKgf',£™©½ûUîh­^´cŽJ˜£Fr?¦¿¨üL9í pqÓ ä¨¶™ËÞ:‘5LŒ–Wëw“]÷K?¤lÝ î¬a:®¬™¸Í2_QÊw”:‡Ñ·)íY7gø©#×É|!Ñ_ýºy×;vï”>!^϶¶äÀœDá§H§çÀ§“Ú)8ôž(*ºWU +õÛ'W*ßn –²IxN@»2§ù¥ý×3Åñ ¸’Oü-„ Ñn½¢_ôðÃbQƒT•Ï·,еÈÜx9" ©¸¨7…DÛWÚÛ8òÙ¢ç¦{ó¸:™ßœÏž™ §1ús“zçÜÑ“"ÊĺN>7œpBžsIåçl(uèq1Áëý2 ;e¨x¹oÂ?¸;8ë Ï5äz=×;‰ô¬Óm0cCÝc‚ú³+·¶TÏÚe–´±v¬!Æ‹F»’xkw…ï¦dÈ`3cU³¡ýžj仩9¦¾š ºµùky"˜ ôº³’¢cíÞ/CkLíÁ|KÜçeåß¿¼>³º±éITìh™ZÒþ’¥ËÄÙpî[‚¯ ÖFN²&¾ÔÍ$Ï5{K–&ŸðTl2º`ÉÊF³mñȵw‹˜jAŸ~þL_ßž&°™x¼ÇºØUj+ì÷ÒE´¥¨ÿê72Zä~D*™ØÙÚ 7Û‡•Vª¬@yxÐA^Ô™ËÏJõ$"ŒHÌlݲ˜ò·Zׄ%´z/{¦šÆç]¨Ø"WÄuá÷ýìËÛó9Í”èÆTõ–g³#6¿Å¯F6YRw%¹QXÞ>êoU,‡~Z"aB]÷äðýMma[lj&‡ïã ;ZJmZ-U„¢dCG9²èß%ñO!HB8éôÄþU3_Þ€5îfEÙÛZ-•2Ãrë¤ À×$‘!½§¿8føÉ ;ìw¨C•Ú@÷þ“€"ºmn\eÍ+ÊòuZèÙo–Ò~ RÞ–-ã´¬(VÈÙ™©ê Ibý±7cp·23UÒt¿×Mstœà¥ X: €v–¹Ý´ŸÇªŠp!“q-}%Џ“,«¨³9õ¯¹R=dùÍiUS'Y¦yù2…JÂ|I1ß+±#U‹¨ðð'E(UßÙŽsˆþþ“b´8Î$Q†Ã™½Xö£*C;iê–êçgÌsä`AA5¬5¹f‹Ÿ‡j¯>_•t?ÕwWÏÐàO6åhç (ŸŽ‚Ÿpù´ÈwÎþÀÚXýy#“Mâ?ôy x½\ß~ˆµü]^$ÌG2ª~¨É+€[ª}-Ê…RN¡¦ºLsÔÐaT?‹~±ðܪy½øuÉ€ƒê«•õ­A©—¦F:e»U4±kR2àË m†â<Ù¦îkô»[Ê‹7Dꢗ¸ÇE‹ŸÄÓÛÎã‘Qµ=Ù4tž£è$ª7>tÅeúñï;ÌŸ­+L>ÞöcÒA7*£(¹Ÿº ±‘_c«Üç\Ä~ ‡šl×k"qÍGÿ"6ó”p)¶K˜Âr µ>Õ¦«ÔC¢\Šk,W|cIúql£DÉTi .q6Î}àÌáôœuú*V?ÅÙ<¨‡]Õé´ád²  ¥9A52 ÷äß°s Ù]M ë€tÎuì±§6cؼRx¯Å1µÏåhLH• ãÒ|ª •2@ˆjÝ›c:«ŠÍ1šóä¥3Ŷ6Yg&wËGG3àåœÌ)Ó.ͰÄÞ½ÂhùÐyOí¡(ϳR¼ºDàvž76<û0c»‹"­õXñ¤t><»%Ƴ~65Dªù€- r 0ÏMf£c&ìÍ·¡Â:–¹×˜€ÍÍ—6È%?¥]Ï÷òÁ5ÉWÇ2f«½8gNŸŒ6ܼVJˆiç¥V´B¢§éŒĘ 2œŸ÷÷ ?8ó!ô¼}£Ä oUKwEž]kSví;1Th⃤ŦªC¨¦}DÈ_ŒÈ»Šã´WöaòV]2e¯ÂÆÞ¹lì)ó:oAß]sHKÊý|˜–¯9; ¢§íznŸ0°ŒyVú"‹=ÞÆ“=-a؉ÊèÛu„ÖnÂѨ@s}¡Ë#m “³Ú‘ðM¯pÈÓº‰e!35•g§îÚþÄIýÕÈïPÿ v@4¯[wÊÚšë-]gn¸¥ØHÇ×°ír!ûîB#xÇ »õóSyË:7)äŸS¤aG;Â/¨ ½ìÓ;nÉLéio —òCE#N¯%ðûÕPZëÆ¢øM4)FdÚh…kŸ¦óÔ‚懛‡‰¿ì¯‡ŸzÉ3T”t§4 ˜Á éÐg5 †édÈ ÐÒÛzd¸›.%¶GíÊðcôñ+ ‘ƒ–ßöcAÞäÇÌâO3ÄÏT‹æªû™‘M`ÐQMyÝ­`œMä)ðøÀ @!aÆÛ&TO¨èÄ öñJÞè* `Î|Í}Ù÷Jåt²ùîÛ!Jy¤½ÞžÞùiuýpêºÙ~™`|# ‘±ä»ÿR¯²?: ßfÔÐï»,ãˆísŠè[áÎâwK·`–,ÅÎS”»Ê"mq#8+žÕH™z Ýdà[vc圙=׳ H=^½EoîÃ÷ú?·h¤ðw¯½b'¦BÈž²ýî{IÕ\ê5%‰úó$£¬6o\b¸š^:X¸Ò,”Êš¾7kòRX¡†—ÒÌçBC£-wÙ^~êy™´Û²Á[¾„bŒÁÆ«£¿×ËècN:æŸÈ«[løæ\Ö$F¯ùb•5ö½ÝZùÉÇgÜiœiŸc ?Õì:œóEÄÓx¶X±ïÅBÆ„}=.OýÉR R^j}‹»TŽ`fèÚÙþ™m˜¥Ã¹ØM0Ü¥–d]Ë?^d'+ÀÅeóúañç»  Ä„»?ꢜâ1׋ø»`÷:ÅÊÍ©vè÷m0îòÚù4o¿¿¡´ˆ~·»üœˆ1VòžñÆî® ýÊr˯ú¡òÛË-î.¡º­Ì9G\ZoÌ âWø $­ ê~ÀöP—…%‚*QÙ‡ØÐl‰ÝH †6ƒnL/\Lð¯#Ó•ôOU¼ˆŸbpjùs(X9®> _±Á›JÌ8¹ø$ ‚‹l0D• 1´B°a³Èùó9¹;>³™»Ë]íE¼jчøâˆ«¥ ®òTûÙ'˜ýDVzyx€šCö©‘éÕì¾.l«¥Ögüü ÍÀdÒ ¾ñAv‰ZšÛqÊyÖâBMIdÀ£j‘yŠ‹Ì 6ïIO‘€è†Ä¾!vpk«I uNB1ïhƦ2A…@GS4(Y~ ‹¼h™Ixé‚>½E¥÷KãïîH¡9Å™ \¨!*ïÃ…Ã'T¥-f<™ŒB|ýIñf²—JL9¼²ú|)Þ“÷aLƒÉßÉf†/Ô1˜ ¸SX° pl-dÏ£’}?FÃC œx@Èg‘ö|ÿ!‘.†ì“ð4sÖ•9Tv@Ïh>’#ßbK'­asMt0„\¦¸èûa×<<Ÿ‡V[>Ú=u°†*êbg .F5™©ƒ¼ý¸oÃAImGSA•-_(‘£lÏ…ZÑkƒŸò¬•o‰*¿@Þ4®"“ºE ÖäÝO¸`“ÌJ<,õZ%ˆãF´Žã·¶?ó?ÁòkY¿1ª"]í¿r?g§ðdš`•ûí#Ûk™`£Šš3¯ÒÛ{ˆ?uBJ¾Èw #Ýõïië-XÞG) ù{m× oáâ 5Ó“nz;]vÁ¢ °Ï*‡j®”…% :qG•м£—“¥DÁ_}mËW³ÎµF³²=âÙÅ\J§LW—¯“ðm¹Ÿ ÖÔèWïÖkFŽÄVûfÈèG§ÐÅ…ƒ)½†¾QM&-Ih|Y¥3’lŸ#à$ ñ…ä¯Ä0{•åîÔrISôÃsóJ}ü@6¼{n ÞÚ¨î’Ã_Å£-¦G»ñ~a4K÷±…T€$ ’ý’„Jš&»+Ié IB¨‚. ÀûÝi qd­›ìðŠ$yœúv kÎÎQŪ,NûÅYÓ[6b¦Xð~Åâí9!ÀÛë !ô뺡Ç{+t_¶æÝã=9y~:Z]žè™W*ª¼¤úˆ±¥Ì„y“Ý)Y!¥½ÁÐÚ2šJY†6âÁËÁB±GRÌܵªSJçáXQ†Úâ$õÐr«Ëj5ÄÅî, ½ƒÛ¦?iØñOxÚ¾Û:#~¦•Ë6 ~_jõùf²JŸÎ˜F&áζ`=NÄïÚÖD'ö,Ÿ­¦†(”‚Òéìת9 óÄ&‰ª&é:ù<È#ËöJDŽƒ° <³eʤ¼á"ûd¬¶ö@±Ø'Ü4'üÔáf¢(óþ`†AÎðQiQóvQuÚsݼa?µx0Íç1Ù&ýÑ8'»îέ}ͧV¦èZ¥ŒN2[zl’8]‚Ï­m‹Šß‹W(a‰>S’PÙL·„Ù„ÃÔ¿Ó씺Òi“Ô·•M£RÓ® œKcƒË­œ[¶Åºla9Q{,b$P¼Ñh,!µ ¨±ÎIs)"𼉘-¦q_bòâ @²¶çNžýJ¥ÄÞñX<Ú⩈Ú[ú<@øLz¶ücb=Ãf »,ÿ­€”ÞêÇm?‡Ï~0ÇÝšHóí5 0” ˜|Ù¼}•¤Ïøtœ.”ÔÁ?ÑDM#4IÓî-ùIÒ¸¿ËíUh‡‰Í/ý‘PN&öž?å5+*ç>b¸Jýiây?ã~Ü2!ó#߇Dá†å=EŽÈ–¤4¬Ívd…Á+Ž­ó Móù·T@às“톷CÉlÄ—8A4§U01>!væÙ`™b‡3ľÃŸ­[N+DÅŠ=ë©ARoüH¼ŒçY*\iïj¢—ÔûSõY³<Ãýp–.Jz¶äÝ41Že‚•0©ÚŠADW¯æý|­%ǯ±WM»–ôß>Šg?Fæ)EÒ,Œu ÕÞ]sÆ¡f¬¹7Å—fÚ[Ýcg®”‡HÏr2ÕŸ× å߀-Ul$À`jÇ¢×ô°6 ²pÄèkù•à”oš>å\fòâÀË„$e´7C$“¼×6N`MfÒ2ÝyÇ©”!Ë=fZ\ƒÇ«“ßÛÝÏAec#!Pß$ø¬œfæ¢$.¾LOÐ4¹{Gl¬WÞEä¯ú|ðó;Ú"÷›p¸ÉMa?ºóþà0n¿+òu0žEsÑ ½Ã»^"Ø;w³€nU'µþGfì߈¬ËÈýÌsÞ÷úq6ÇÒ ©ôæ{¹Xæ¾[ië3*ߘ†Â†^íA×¼ÛïÎ/ªõ3«Ï[P_'¤wkZd M‚zúHX¸CÆŠ³KãŠÕrA &à…0b˜4Ò×Ê#§ìyÜÏõ6‘ìÌk¦/-Ñö>xQÕ‰æÌy]vÚ«Þ ÖêØzå?à4F4)Gù@­^T4@þ¶µÔI-º~ÄýœdQ)„:ÕǶÈÁJÉž¸„‡ž±t÷ÂVŒ…EÊŒL˽YÇÖ\ìÈÞœéðsÄ€iCƒá‚ßCJ’`i^lA™;‰-;ß²wñëÛ&ºK÷<«Ëxhõw¯ý´Vq\= Ýt‰³Û´F~ú‹-×*­e™í¨Z´«ìz\—íœO?ƒÖü‚XtÙî$MGÐíæÍ‡TÈHîDC /ËeèV{ÍÉ" Ë ÏYOÓ8|@H}g6¯ÊA~7¼9¹^i#¤k c„­A#MQ¤fV­¦çÁ‘ìZË™‰Ý5mÖp’hCå­8h÷¾ôÚÁ?-ÔîEµXBO o„P¦ì2¹u[²DõñëÇ3ÿÈ“k–¾G?CwÂÖ¨LcûüÐ&”Äe»·ð ƒw‹B0[x„!郓,pàçÞœiQèœæ1¾Z:÷¬º5$˜ÝLôSHë~XÇgÑæ%•a[Ž1þ¦´'C5 …‹ï7²ŒŒ`šE'z¯=ƧÇÿ½òê*ž(Œ RD‚>ƒ¢*2uSm'GqC: -ýŠšx(´»œ¨w­Æ =ÈklMƺ»Ò¶ ņô‘þ»³qÖ—È4&MîOÆKûjÜ»áÖ®6©QŒŒ.ˆªSã/=ø$™ŽôrDÙ+"bOÅ{GÛ–^é]RwÎ=×aà$`FÂà.tAæl©šY²ã)i¼‘CyÁÇ„9VòÎ÷d‡f°Ú˜9š¨aÙŠñSî?æ“~‚¥®½oùyk9ÄÔô­¤—“‚¾`£×¤•:ƒbºøýëòÍ©) rµÜÇù\Ÿ]ð©<ߌm竜Tõ9EôÞ-ýXC˜-Š¿xYá–ž ™r!á; QI½-©³GÈYflÝœN·Ê3¬âsj_ù j¡˜uŒpæ|üD ‚µ„2õµÕÏÏ!”%vqbÌìÒá²ì—2nDÓâ‡mCŒ9^11~h¡“þ4RÈ ÇÒ]ˆ~|­k˹aûªô޹ò"G}}éÆ,õ;¥/}ãwŽ.Sþ‹èx’‡¦›ëÔÀ¬DµÏ|FµTâ$µn‘´Þ¤;‘ÅG½†Sõ·¹—ii#R&AØÕþ6gvôEï<Ï×}Äy1c\ýä+£У›« ÞxÒ\ð1ÅŽlo¶„­•°^§™©q®•ðr£W‘‹ÓåÑ¢-«ˆ ¶tå|í–Þ=X‡`ê3x›ØˆT]óíþ~…ÍrJ±õɘ®º£<žç%^¨Ewα°)­÷n!ö]eÙ'îUí£±‚ƒ{nü£¶Þ& òØgœ)V½ˆŽ‰ ì5âƒîyÅ×e9>fH4Ãn!j°­•·Ckd>"Ü,„б;K,×ý ¥Û:˜‚™Ö‡*³ªg÷Qöð”nAr*uÒ~Í5þ¬1‰ü;¼¤‹1òï2rêRÛäý£/‡žXÕ‰O|7xr„¿ þLv"(J"Dɉå&T»P¨k×Ó]d– {U,WÔ„ oxþð…NöúI';„qßÀè< Èü],Üv{ƒO×úSe¨ëË%MJ½‚šðO…lGÃiWäbW¥Eü?NòÂ[ÆÉŸ!<¯÷?7³™–nXÙáþ…íIj’þTÉJ\^(ËJ‘8Ú`I¼²¨:mƺ/øw™õ/x†Es”•Ž] ´$à΃®YVLü3ÎÉÈ&‚Ô¥øbh‹IŸÜ1þŸõ$ Û©´*‚|¢Û)ƒ¤UB·ÆëF1Æ~Õ¥>¹£>â¤ðµ f(š‚,äH^Zk-šbÇi$ÈÙœÎK±¼ }RÎÆH„ü²‚ü@  g­$èFˈ›Þ²‡½\ÎÛñáØ9 Fó¹…±¾.ŽšÛ"Å¿á­#}kÉS;ÐèIO(Wg¤‘9'÷›§vlO·ð³¶Ý|áXGES Ñ̵¶t$Vw-ö)Bø>›ZÇb! ÔÓ ¼šç¶ (Â5>ˆ·†ùÄAyv¿6&­aà‚¸CÔ—E±¬T–p(_\G'„½1zoëN®Û©ß™•"=FnTñVüUd߸ t _øæR$J \¥EÚˆ´A]ü/ &%l²<æÁVñd^`}“ÚŒ7 ݆ì ÊÍ0c,©Ç:¦Ièaæ#õµ) úêZÅ¡$pŸ¶>éÝßÌZ‰ŠÚàñ’¬_ŸÐ8V¼„p1izXìy[¸«3Ë$R%³¡s_|'ÈÂü°síüœ%E@´ëKÙÓ>V’®áGMT r‹3.úÅÜ EASlÒÙ"ë¾2Jh;Μ_ƒ)©Î9ŸÁSMÍŠ³kï>kO‹ã€TJ¡ðsôÿÕâˆa%ùNq…ÖqÔïÈÈÖNJSm&dˆ¼,ËôåÒ%Ô¡w~HœÎEh6gÔãÿu-Ç®ÓÞ¯ˆNÑ>sß­ƒ&cÛÈ:Y&f‘5A°F›!'QºÏˆY,FÊ•`ðæ+eè¿Ãcy^æ¥1Íê—?ÜêŒJG,De`í ƒ£ÿ·ŸL±ÛÏutŠÙÜSß’‚eÊeÜm óà½Õ£¡ë%.÷ˆ}ÇÒ$3˜‚õTDÈA Fé‡ï¢Ó·|\·‹ànE$dŒi <Ë×à´ –S¦rMê!n¡åéÄgÈóá»ÔõQ¢%Z&Ú4½¹z8EHÛ÷õÊœ™‰Eáö‘ê?£‡L§>?r§SglWRGÆ;×# K™?;±Õwˆ› ×=÷É3¤Iû§Ê`¦Ú*XÜVSTõ±ö~Ó]9bí°5Ÿ8Eß îñ¶] ôm ’ùÁ¢é¨î‹ø˜´Ò\)rj®ˆtÊmÀ%ØeJu „¿KàåR¡âÐr`œ.l˜æ „\f+dv5¼˜î3ñV%’Õuj ÁpßVU ›ö…VYÜé#×¾¶H[‡ÀDÑI~pøY¥upÇVÊ=Û.㺴½y6OEÝžó[Ógà%Ós\vŒHãS žñˆöG”é³»YFȼ̦þܯ­Õ…Ñ,ÌsÎFÜE4%¿/Fœ:ê2µm–Ey²¢Ÿ~÷ÂÃ#F¶)¸2ƒrƒÿÇVð9(k5¨R¶gÿ¥QÀæñl‹V´–ûP¿½¨ÿøÎ–stÄðŠÍ7ÙØú„IÈ]µE öÞÚ+¦N1äWØ~\a“A-¾®]m÷‚¬xöŠʘŠýjBÅ¥ÐPÈÀrˬ-ÚƞɅ?!Àe&ê÷4$87°RnUö1¾|&a,`[ô•¼¼¾ŽÎÊ­‡ÍwÉ¡$— S¿F3ñ‡F©:Ldoqñ=Èžç–³¶ÑxÂËÒkÕ¥F ÕԹǬ¸øð°CG^Ä:^äI¹Xp1ÚíÁãy¨%<Úìkf½ õü×@ä Ï¶¸ó>·¢áúÆÇ£¯ö„]€XŠC;ÈL’±L§¸ø„Ϭ‹H( |ñ˜‚„µ±x¾ôr‹gÉû`}“Öœãç’é½ggQ¢äö8>ýýsÑ´Ÿ-<Û–ÍàÇ"„3%tòG`Á?tñ†ËDŒK% oh¾¬‘‹‹ÝFüóÑÅ'”Ë•¥®S–žå-Ùz`‰t–ô ÏFº>®ÅK̆Yó}zÓ åz;jë¤ 9•Q^ŒT¶iÊŸ|°åJ–yé¦3õ/‘"ÄàØb3’ƒÐª¨,ú¬j|í:æî­%÷>¨‹Œ¤*; c´TOnið^³³Ô <4gN&‹r4wZ3‹’tüºØ—ý:|f¨ZNâxß1cµ§!9±•ÔÛ4Ò›JîS4’o•|vèb«n‹fñaÖIo#iRã¹²£Œ÷¢lãÓµ'GœÏlVRïôlËF„„‚ܪ¶‡;{ϬÄL” ë=ãSJ8»Î7UæŠ>n¹ÅW9¯¿»çmöûaØœIfZ¾BüKÿU«Œ žË¾¦©Ê}ú–. 'ÏÍ’00<)ì£áúñ‹ç†¦_ãdÉÂtësGO"vk¯¶‚<Ør”öKê‚Eú›|u"weÀëúe‚8‚vAËÄ® ‡[rqYgTŸf^…à%ÿœÛ;Ǥ³ßœÒ ëL~.‘¯$É­Ú<׈á…üŸ >oØs Ä Uƒ{cZšŠ—J¶Ëí]¦èàšG³ž ˜%ÌØ*Ÿ/Ï)§º7-Ü"ÿaŠ7óÆ~6úiZ—Ð-šÜ ¶ ô{Ó¯ƒ—èˆá£À9$´m×üuÞ}óõ8[Àe¬ç‡'‚q`0w¼ff-¨"Uä-*ƒtŽ˜Æ„*¢'x|Ñ:ÛDU/DÍ õõ”bq+ŠYÌ„ÁòípLÖ¦]E9 p½Ûœ¿©Ã—¿Ð'YÜSÇØNÅY ÉÁÿ£]ƒV“Ñ×AH')¯Ðöù²£Û˜ûã´ ÞeVÿs-+â¾Êo:‹|¦*qÿ“iœÍ ÖJÿˆǨ_ÑüŠ‘ÒpD2§Ï¸½í0Ÿ(ËúÅUù·Š€§nµLöåŠÉ¹:j©Ol¦¸í!-ÿ§v®Þ,I Ké+ÍňZæ9.ï1׊ɭ–rJ1mþ‰OÈyxAà°Ø|š7‰,¥Œ2”o-Ú\”Æ=RŒ'n”Ž rÖ‚‹›ÚÑ1ðö`è&,Ñ ¤”¶Â¯La5ócÃÍÀÝg3›û¬"´P¾hñÝzÝĶCFš/ ¾ÿ•c¬û,`^b…„?ÃQ)ftbfÑ#àú­üǦÞèUYÖ'Y¦(ÅÇ]ÿQtŸXÎÚ]`uø¤¯$MDtßs:º¦Ž”+ï"jiBu3RÃã¶›o{‰ÈvtÝRæg·”;ÿ<!ŠuŠBñ3¸šO³BG³×°·ÌÛM-öA&.Md)"TÚÈE¥ß¾Üš×wDr›b@òßËáÓ*9kÅ¡P}÷•UB‡P[…b¨l‹Û4Ì÷Á`ÈÈÐQ†OvQPCÇø»%^}­;"ˆH Ô½…:8ãvø»êÛø]°N½#”#|ûƒž,4;,JnÆ;†±×ˆüâßœ®P˜¶úÔ­`>ƒ°þ’?v^Kå ~QKþ9£ÚÏï×ÙÄ$€’…uâ>!T¬öïƒöË5­é²aû<Ú‚B˜û(ÙòÏÚMJK¿t$äç_ª%Š·ÈþÉSâ¿äé¶ŠžôYÁæ¿FŸê¥Ø\¾QâŒïW’ÀAÚÅr6Iƒ¨Î7‡¹\Û-jè§'×È]×ÑØLK9‹À«‹ÙéõG}7¢dé—tZ÷†vTš‰4ƒ»ÁŒô&…ݠ|˜Z8;«TÜèõ"Éò.äM€ fª'I b‚‘——¦RÊwジ»6U"ÅsSè2åÊq'] êÕS(êàfŒQŒ†èƒM©f±'œacPÃ)¸V–g$¹ãµhE}ºlmÛ„áÆ3 ¯yÖ(õZ}dºîMŽKÒŸCÏTGo®ýS°H0>¬õúé;_Ý7Ú?ÜëENª~ôë%Œ%gl.¨åîG¾D!©^kÊÔ)E­ó¡ò#øD^E:þ3='C»´ æ!#*ôå-ÊžÜ¶Ïæx<Ü(Å—U}°%#øöLßî’%^ߢÜDª÷ÕåûAÇÒ‚y·¯dûÙ®(FѶ<ßÎótÉkJh¶9+aVip¶1â‹Mv˜e(§ÕQ+I=Léq+$aŽ]GWMÒ5  N!u ¾Ò=ŠŽ=c¢Zb³§ùåík¨Ý®NEïÆ³Ë9Ï9 bMx¬J: AqÃ^Éÿ¨”qÅÌ:µ1zOØn1Î üXõOhñBÛX?^µÄ¤gIŒk, ŧ*¿ð+ýWa^ñYq‚!þ–!ûêåj=¼ÉˆvÍ¢Î'i E4ð2ëBv¾äÍàU„SÉ«ØÍ§X¾[y]~»ñ¬ÚN¼¥üþúße›,I¤ÔAûmOýE$¾¥½ýî>G·&BÎϺg)Ò[6Jy/BýM` U ¹V¹É‡aÅÁrèQ•¼>v»¬¤…”¡Ë £û¨ë³Æ+õ«Kª¶A ”v]mÈXƒnf®ŽKˆvB¥mu>6ê­±k3o@õˆÆý©¶åçP(ËöÇ®­~œrBT€Ž/Ž—!] fC=Æa‡AOÞ.v$Ï—œ÷k©ø¦iÙˆoäÿõÓ+I¦ˆå”ФbH“K¿?þV‹Íd5‰âó¤ 'ÆUq{qu´ê¦ž´9"Ë)ô¹ƒÌ@~ÔÓ[U}ÎOB¯ðŠ Ó*þŸÔî°˜¶(ä=Ü›³,ÿÌÇŠØé;d¶]8ÍWu‚ÝÏ×½ÙrßÑ.dÌEœ3†,9ʾ©5Å;~|¾¿Xœ¦a÷JCL4>ì ôöOu$5îç˜þÇU·/)ös.ýPнmXsÃÏ iN¯nŸë5‡$äÕ˜6ZñËýîK2Yÿ´î7(êo¬Õ5wà<³´YªØ«E} €(ÿ–tpÀËÊ¢­Ë!ZY‡Q[Na[©F±¸&«ÎAcQ4ýàPö{Ï)2›kÁ¨'Ä:¿>å€ïè®›»Fb-®o¶xob÷Bi+È{­ÈQîQøµ°ìoñ IÃ(5qÝ/ÅËtEQš¶  aü;Í0,;=/Ä[e.Ê8VYˆ’9Ç&}BÈÚM·£j=‡\±¥ÇCK •#Ìñ¥µ”rkW5«cÒHYOEÁßqDÃÜ®s•2e‚<àíc¬¢ Br¬—ž_bmÞu§N·uwf9 1¶272 Ç=H:]PµÉÖ›¡âì 5@;n"€e"ŠX5i—Ùi= ?mÿPAeÇÏÙ?RñÂïͯQ܃¦!Yöºt“Œ£ëδòdWзÈXÿ*qI]Ü Lʘ¿\ÐonwŠÕ¤îÄH>Ž…ìë° üÅU2N’-µ-m†¶,à#RUó¹xá=Ô ›)©ÛÐ ž0{ÂIö!»½÷ä"ŸÜ*‘°œA-‡­¿~ ØQ YÀãñ°ÒmÁVI†µjˆ&2C׊'®IC¨ 1–Ç‚`;£o•ŸZ‹Êžr3M»7>cTŠÆ¾a´cg¿@iŽÔ €éÞ8>Y¶ʶi8ó†!—o§g¡Ø‘q½øþ†ß~ìóÞWׇÏVrsE,QàþNÑ‹ºÖ6Ïl\ä|Å¡N¬¤U=Hö+‰¦–>¥"‘­P3ÐJ›é,€©Ë†hJâ}…6ºÚkiêg[þFéuÖÓ{B}6èñÕ}Ž‘é~ƒtéþUqXà/Ëf1Ó¯-(~’BipÖОF.\oDô„$ñró"OP‰‰ñFö‚Å< §~ïBõFÖÖLÙ]ÞeuÚ#ŽpåŒIV¸)é™ ¥më=Z…݆ãïÖö|µ‹s¢*¿49ëŠÞ…5Þ`ÅÉïû¢¤³ºv‚uËHÏ8;eXqN7XðÓ €%‘P:†e˜óClØÂÎç€zEþw쯵ÆyÐ_pŸêsUÁº÷EÒ}à¦-+Ç;Ò~Ó;!•¾fËèS–Øý?meŒš‚§HŠRs/%~?•Zþ#E.À„Å+xÒæî|gY Oïudâ6(ƒÀ´¨²ñžã„€Çs=5–²&Õ9þmU&¹ðèùùkÝõz$3WÀª_7ßpé†Roÿ²õ¹K.b]jÓaá–¤Ÿ×Zà©+‡n¨ µ#R‰_O{$\¢1ãL™'Ÿ.#ûœáªÉßÇŸqåÏEϬÏðQDZ?ÞW€cDDÉ úÒi‘j:­ª½…Ú„‹©Q kXm*œ„ø¯Cýñ\¨ìÝ9ôvG˜÷ø½•ÙJ¤ÉàÑ/Åqˆx'ä’3ƒ)Y²‚f³>0Oë¢t½ “ÝŒžÁ¯yÚO.× °Iøžû/ÆP¦<& #ËûɆ&/Ãvþ€Öì:€˜×g «ÛC;IJõFë6·L þ™(Ó¶œhkÈŒûé³ÉÆfÜ¡©A—™»þÂ’(}콟è¡Uô)È ­è&Ž(sAžý«A–ñÜä8 €âM"»§(9DFVEjô=àБ‰Éà/'8©– ý͆çǼ‰K…ò‹Òè÷éOÚ‚Q’˜-U“‡ópFîbò‹t§u,xh¸©ËóØQQê /oÚÆzc)âÄ.¢ðžö¢úÝYV&þ¿YɃQ;ºã ‰¯Šñ'`q¯œçæk½4µ«äÀ¿ÁŠ`¬5&5ñ¬ÖþEÃb‡f¢ÛÏï+cTk %ðýž˜Þ9Rô!Ó.ßö 9P*>‘!Þêßí09è…SŇä‚YòÑs–d'¨ñCAÆ;¯ZŒy0A.£”,¥Ú·áU;ÈÁÈ™(Uà\Y~Õl°pcË‚™ÆUkHÆ+bŸ‹] ITµ+2 lû:…“¦w»ñ&S\ºoÉ•b6*šDU 7p¼ñâÝŸX/ÚÔÈdL¹Tv.ÃÃî$3ÒR.“”mSžìËèjÒÀCÆ‚OWÔxïÑÖAŠÀxÂçš@×›2Ò%EŒr%SoPf6jQ+rÑþ-Dûq-þw¹¯L`Rp!¢&ab;1«Ô$Éfˆ§vhQ‰ÕÓà _êý¯ª§µ$È ¡–-‡ {ö®h•YÆrÅ·Œ‡F·v µ³û]8Öˆ­¤t¢¨íÃbFCHe[ôÌx¥ Ë=šNîVÓ/Ht½ßáËìnOF‚×̹ã¦Ñ~€ñòÝ ÿ#}_ú÷`û67¤Ñ”»úø ÐMt^{ Lg)4%œ&9%˜M8Ð[–¢ Mó7ªÄeú%4‹;D®)1_ýÒ¬# 4ÐîÜíÒö“kÛ[’GÕb1dÇÁe™tUXS™RÑøƒý0>šÚ¨ì¬{O,» ²OU¼/„'½wÚ &ª2æ÷ä¡›ñX¨×œÒ1NµìFž:£6¯O±ÅÝlÿÊ2ï䦿t)Þ-Ä’ªZ­%LÔ ¢O“¬Ã3—9câ¾f3àÔüQÙ',nË5Äǯòacàc\ ;=.pp!aé9_*kžT9Ê9œaè®°ƒpí;Ÿ9‘¶Ú‘lکν<‘­t°·Nl³c(ß×®Ž=ÈÌ(`Ïv;¢Èº’G&z/÷®Œ>‘TÓ4Föp7už­Ç58çÞËeèK¨ÁðCE£uÿWÃr»#¿d‚·ö,(c Îù×¢>WŸŠâÐC*]ŠþTÆH®æò$Œ£Ðÿ2Pß»A™#Z‡fΛìŨÖçûð›kd*n‰&H³ðšd7‹AMki?¡—òš¥âáðµÜœÛ{Œµû}OúoÂpÀôÈémðž#¢Ò¢3ß«X›h­nÊûÒLSû<ªôƒPã uK¨±i?3ø{/)ÆLl“¹è­çlÚHR‡ÏÔo‚¹Æí…$0"ùçSQø…˜á.ÙßÛxLî#©î~-%ÿùÓ»ƒCÞ+€Y;¦¦%ïÏ6;ïTîðÊIYÚÑ'Eƒ» ¥¯“*‹d“'E™:IJä¼_p¸;›™ïÉÌýÂõSJfœ<õÞ÷•‡jœ¶ÒV>ŸðŸÔU¨#E{ÐçïCÒµ©°W¨ŒþÔK,üš‚ô¯ ¡ ½ƒÈ–ò.›jÆ„Ô?ptåÞ•+\ªìkÝ®AË~øØTèæˆLäÍ–¦¦¬¾¼Jôz9ºÞ,ac†G¤<áFÝ  •‹õ’¹Î0àˆÏE1šÑm‘š&k°ã{²"ûNÃ…)á!³jo˜ èe@èÙH Qü÷Q.aÍi‡ãc!"uQÔèlž~‡V ºÑØ6ÂlÛ¸AQ¯ïc·îÿ¾$†póëƒê‰TÜ«ù­˜Q×}w}ä‘Kfã¦æ´žûí8¦Fá6¤[KªHŒ©=­ÀK¹8¢/K¯¡Ù£ˆbš1Ö*õ®Ê=ų ¬-*Ó‹¦7ÿ?ìvԨł´ÎÑ]`6Y7›ŒÓnÆþÛiê9Ëg –\êS_Jj¸»oùVÉ^u0»/²rø'sä2íú•À r´íÜ¥7ŠTgýÁ2YÁŒŽÓ UätR~ó?»ó·A6òì0þ¼#dX$Ÿ5 c2i'0j°E¥@yè~øXÊùB½WDM/TJaIÃ-vî\N¾®®Ë.•µBi¹rLw³ñÚq]Ͼî†g V+ªëÈ¢(µ‚ò¡²“{ÇÄdò¼aIÕ“ ¹§1bä§^ª.„›7!ÀwáÌEå Þj•N­ÿŸd+–ôb,íþ—/ç6Á÷~u¾Ä¢-‹÷8÷Òq‘t$åUþåÇŒÿÃ’õ—R¶Ðon‹CðT4ñêvÔç¢[ˆ`ú¼FšÀhCÐ."í‘X¯Çø0½*ÝCèÇé!h3Ž ÒŠJu©6f†“wÆ6IL UBPûîŒ z° HWÀÄøhxjŠý|&¼Ùwyèÿ´}“¸þÚ‰ý„ôogC/"ë½cë9e䇥ˆå=Í„u¥ìYJËû†lŸæyPáÿrlá«4ë"S¸‚IBtPkfojò£¼žEí€Õ q7– ©˜jHŸBèD endstream endobj 827 0 obj << /Length1 1692 /Length2 9349 /Length3 0 /Length 10431 /Filter /FlateDecode >> stream xÚ´TØ.ŒSÜÝBqww+îî H Š»»;—"ÅJ Å(ÅŠK¡8 åÑÎÜ™¹÷ÿ×zoe­$ßþ¶œïì½­–.‡ ÈÅü ãàáäÈ©ëðð¸¹ù8¹¹yÑô 0'ð_ft°›;Ä*ú/970öd“žüÔ] '€GP”GH”›ÀËÍ-òG7Q€<ШsT\ `wt9W7ˆ=ì©Ìþ˜mX<""Bì¿Ã2Î`7ˆ  PÂìÁÎOm€N]æó_)˜Åía0WQ..///N ³;§‹›$ ;À ³è€ÝÁnž`à—`€Ðü§2Nt€ž=ÄýO»®‹-Ì è<œ 6`¨ûS„v<è*«4]ÁÐ?Õþt`üu7Nž¿Óýý+ú;hcãâì „ú@ v[ˆ ùBæ c¡ _Ž@'w—§x 'â´~rø}r à…Œ6ø$ð/yî6nW˜;§;Äé—D®_ižnY ’sqvCaîè¿Î'qÛ<]»ןu„ºxAýþ¶(Èö—‡+—>òÒ¬,ÿ—Ë“ ý›àææá€_ÀÞ6ö\¿Òëù¸‚“<¿ÌO ü\]\¶O"À[ðÓºŸ;Ð €¹y€üþMü7Bçဠ60€5ØEÿ'û“lû'~j¾Ä`Êý4{<î_Ÿ¿ÿ™?Èêäóûïþr)hi©)²ý©øoNVÖÅàÇÁÇàààˆ „¸ÿåoýÿÑþÛª„üu6î*Cm]"Jxº»ÿÈðük*˜ÿÚÀWÐpye0€ùŸÉ7ãà¶yúâùžÿß!ÿcÿ+Ëÿmòÿ÷@/<œœ~ÓÌ¿ùÿ t†8ùüåð4ɰ§­PwyÚ èÿº‚ÿÜdu0âáü¿¬2 ø´2P;§¿¯âþâ iA`6öŽÐºð”Þ k¹¸C~½5nîÿážöÍÆñé=qêÕo ü´Nÿ]Rjãúµw¼‚ ›Ðûi¼x~òweKùJz‰æÁïkG jdgªv×ÿ{ËdÉ.ô…Ïăe_eš¨Ð(9ô¤wý^ú;"vÀPa(zé!Œ­UBpãÕ¯èݳÎÛÁ¹#Ä(3)"¡rlÜz§RŠsm þéŠÊº·ò¹P‡µ;»f äQÓI¨Y@Cd§÷®°Ùw•™¨Éˆ5RÇž(½™Ú'I_ØÌˆUºc7tO²f6d³:ºJØÚ.‚m¥@ÕÑ´i—×ä|°ªG;²â=¬&#ZW°v¤­bÉÇ7 +®{Ô<Áºð‰C¢¯{Öª nûþy¿À@qg”Y^¯ã±ÂŒ»¢p;ÁWˆ!Ã'pè·¡”"Š!öAq¯&Ž/fXÄùt'I±ÂAjTúàæHÔ¨_²Æ^}` ß÷bâ)r¾°Ð÷,}W€›Ç©Øß¢ }çmrò­,…Øw:÷g¾nlªú% KIJøH[Ü7Ï­iû :qe:MË÷Õ²®þáßí<û¶Ž‰­¿8,³ÁP"nSSŠO`:kÕ°x3Ým%2ò úY¹ÚÎÙãD“|Ÿ¸ÇE‡ =ØQ©×L˜ui Ö^`ŸQ¿‘2È©œ"ñžÊ5³¡p…¼UÅìÍÆ9ÈZù(¥ÅHœËÐoÒ?Ã’ù³Œ<ÚY»Ÿ‰@DpcAY¥(¼Ã$Ÿ‡0ùœÆˆ»ôl´=ç–íp´j.{A8…%5”bWôy{"óºiÒb»­Ú %ñJ„8G€ó’Î÷^Ù»S´·tweâÄ8@goÂnhGäUÃçØ“þ‘/mµ9S¤›Ô)V[šõÿ¤ÙëIæ…KÅÞÁÒÈ]˜xPÇÜW¾ûà㥘RÍkɾµ-•‚¸f™B–‚OY5‘¦ýh(]µ„9TúÑ}È>'ñ¤WD®i§í:…úßÛÏ ‡¸ßuV$…0ep|É­j&HŸ„)?Êx³Ž•ÒoЮØÑè ’*éÂQÖˆéôÀë :’¢uz¯¾X;ÉkG ¹¿ÌI®×/”Jz÷Ök"5Eª±\îÙzQ†5¡Å¦cnAÕ•ŠX­ ºFOëÖb¼"eÏë²/‹þ¹)3}ÔQúe6ãõë%ûØ#•N3©‚Sö9‚Ȧh¼‹ë­Ÿ “¨iL¾xê_æl:½Óòg`1jÇv>휯ɧÂÇ—`|Dß«%¾TIèsÏ ³¤*kJÉFöI\$÷÷Ó )‰ìo)Í”ÍLrPþNŽL4œÅ›IþÐ $Œ¾¯`À|Ì’âÇ~„#:ägN¡|Ç)ÿ 0NcU0eÏäZ;µÅæî9nÑ$;†§8LJ'O%šbñ6±µxº0‰•±ƒÿÌuÁmÓ;þ~CŒH]”ha“ë(}¦k9–°C#çda2°ô–㥈tçä:øq MúM×ÏרEmþ1^ê1n©6„"ëZDÌÛâŽÂ]¨ béÕBCJ\©¥mü™:KJ¤]ï릃Pævô[‰æÙ_Pú³®„Æ…!ÔÆiv\£±IC5t1?›Ò2Ö!$Qî ÐúÏ~wf@ÔëžplÜxvàæÞh,­ióødhÅ EŽ£-Lué¥ÈgGôS쨥}ÅiÔmœ¼ƒ÷3UãâÊ£Gp3Kn.–|ÀXïŠIç2nˆÜa ®ÐeއJ½ ö3‘ î4UTóg+טÕwéнéÂé„"8¢þö„–tì0YÌØ±aúcàl£šLr 7±²vÙ…øšJæOñcAÔÅÅmiXüK£ˆ8É‘DWe’:†Ffj£KÏôÑ]¡žx§™Õ¥ú xÁr¼g橽¸l9w_Þ8%_Z ]0e}ýÌ·båȪ‡ù–¹¾Ê¼ GP@gô—Y¡îHF…–Ï]Ì*Sr¸R:†‰lò³zXÁ½Ec2Î¹Åæsõ'çò­$fäǨéóc ^¤ðÎL¡ï›|E—(‘ž±™ç$u·A:¸eÞ‘þ&´8ï½€ó¶o¦¾´Aœóâùù)¸¬ë5˜È³¯U—?òítã¼ ®Ñ´ŸP‘ÊÎi~'iQ/âY8äÃJʤì kŸ®iÐd†”¦©MSìu¼‹úhÃïA´Ý:ði¹Q9­¬gE(Á¶Ev‹HtëäAŽ }ä)ÖôwgCÕ° þ{pòš’F”[¿Rr9»fª Ó—r² <§’fšˆ\ô°Ç ÍCÒ%:o Ú¨¦^Á3ƒŽ.æ6Z•Ö6“÷>FëhÝ•´æ ¾ó+Òóœoƒªn‰0Ž£á&8SåÕZ,Ý•vê^Ú…T4pQ»íU„àîÛ7h1¤ÆzjA‡2z¼‹fdl¾dvN—܃V™ÃXE n\âAVQ%%2êwZÖaqвäȃRŠ9]kyô “ãÈ4¸2³g?ÃZD0ɪ©€&„õF_ÏþŽlÕÉóƒH…% üí Ù½«\nÎàW*\¶1ævõ´ÙwKZ? bS4]‹G‡`6rV³E›Ü¹ ýMAõµÆ2ÌL)Q<*9,˜ä iÓ£P)ׄ„ àK¼’³†ÛC&–?,ù©Þ¨7°µ‚æ$-lÖ bñ¹LaìÄd,µkDp @“¦¹nºPŠ÷š",+ð“uw0,Óû ´[š¦WႼ֣dg˜žPùjùÈ¢ºØÄ0®–$º).q¤ûRï%ÕëÚ·Ñò8žÚ÷°kÍ'¦Zä¼›î¹5ù•߃0S¶ØS§¤ÏÍÙÞ&wÇÈ-ãøv\Añü¸uŽôë?¨žÅQ²3Î/PÐ4š‘Ö%­l.áQ“m¬™À§SÙn‚o=í¹øÙwÖNåJBÂM4 „ûd®‚—¬*d¢&ÿXš~i»«ÌSI)5ãëcåbŽS.P,.\BEmŒB"‹ÌÂe+nªr»Üäy,8ÿ!ÕØÐ%òaÇ·Où=-ÒëÁ·nx`EF®2Ñü(úîæÖbvÉðÔñj¢{qß¹ˆj—êÇ\ € ÏpD·>óxߥo[%£ô¤Ÿ1*( K½µÁ%Åž»!Ä”[ÎÊjâ°Z¤Gj¨S÷\G=¤:$öogtïû„Y/hDÛoGMDš¦zám‡C™Ã@‹ ™.3.4ß+,ÃÒ\x±·ÄW»ªÑ¢ÞPaõâ PGz«')°@ᆲ3¥ÉëšÌáÞbNõ9ô·} I…økrî)ˆxYë"tºÈ¢ú&mÌå ·Ð¶æðÚ"”ÍÝ Vâ~Y·FµqË¢é8_N6$çÁ”y¾5*;ãi…ïâ‡&«RõjÊqkÈTmHˆØ HZx1#{·ô?.(R7ö.Á„Ip4 /ç”äGÃÒR²¢?Ôä”Ó|  N"AXCznÿöᇞäE=Þagˆ8Úën|@b´Ô¶›)CûÈ]1ºyŒ†D~spõ(Ë–XÕØ_ú+Z¹2³ mЃ±vxR }’…›)¸0;çP :·*.+:ú΃CòqY-^ÓÐIajQì&´q ÜŸ¼Ê wî{åpš–—òì…'¥Á €&ZõtՌɸäz0áÒ$$¦ ž*:jÎ_„5¯{{ÍÖMgãmö»WÐ6€š@´6þÎ1—i B7%©ijH¦Ž¸‚ä^rG±£Üî®ÁAëvýà4b¥z¡–—XG]7ÎNè19|…´+§d"n)a_Éã!h¸Vý´MôäÍ6H•·úúÙ÷š£b¯–+qÚñn@’a1ÃäÏF±Ç2n±hì:ߣ"Ã;éß»x–?IJá5?×fð•觯ԇƒ÷o#RÔQ̼mY‹ôt^Ûn&a¸ºíë*lž"4¯•Ð’ »_±ä]šq|¸"$`ü:ˆ€q ~£(4Ÿ‚\®œq×Í­mÛËÕ™|óƒ†lý$·L«»éÏ›úâ³Xü\”(ˆOôJÑ!)ò;Ë+Çôœ±Eu&™ØŠeI9ÊÎuu‹€;óš¬G;³WÖð#`VQ…çdæ½n<·?ᾜ÷ Ë‡rˆF\ª´†tVÜWÂ¬ï¶ ýÛ«·¡¼ke!snÅB“È ”%Þ1“ãüåB±Ç´‡½‰.p|5+ú³;_ÞËõy˜ÃY£ Ò]Ú'+]³·ÆHØo8§¼4¾<ȽIvÜñ!¨yµæ¡DwÀ,Œ=¡!Ô ðÄYçR&¡Æ°ÛOåV·%÷[Hùñ‚ -5>T×K ê ÿ†ûõîë¥ÏÕ6ж,4¨2O†OJá:S·P~y'8ÙfBß_ó¼’­CŸŠ¾ÅmRb12:©žšôв'`5–^ÊþeƒkæÔÂML@Š\dtáGR;Oc^Ñ‚Z»þ=/Ù.3ÂUÂ/bÚg8›{Fi\’ùÃîér_ÿ\½±–-eõ­[ÖõÒ0ÁD¨c6{õKâ™y:ãž^õ¬;ê8 ‰Q·ßô„{!ˆ¦p•bz‰SüiÚDC#Dž‚jëã=)Q\©? þ©êž¤ÀT,§³êÆÑ´$jD(—Ϭt%Ñr~ÂgÙÙo¦Æ4íïÒ®Ðj©8¬îñâÒ£Ó’ÏÆ“iË+8ü«®t ÔÝÑ@ôxñßk¼êÁä…uñÇÌ œVœ×çX°žTt+Ò³áÀ¨‚ýë–D(ÏŽ=ê;¹ ÖÉÿD½uÞ&\ÓlDø¹AêõÑKÓƒUcèÛÎÛ&&?ûÑ t¦W¤VéãKáFÞ‘² <¾³’Oççó³¹—%¡œÁº9(lÃ$ÒŒ8Ý1Éfý“æ=ùÖ†ëÅ´%k宋DÀ¾oÜ)¶‰ïœW¡]Óè òñ˜-®¨ûrn¢gTx;3GÚ¸H¥ÛpÉû„›cù†­ˆÄÂ~ÔÉÎrú mbmÚ°Ÿ[ù¦õ1&ëÕøxƒ9-þƈÚü4ûrâD&à‰…o$.Û;wòqØ0¦â=,5íßšð&zö 2êžR¯J[ýä32=ÍšsP+·"õÖH™sR4;dÈâ?{uÅæ_xTÐ QŸ‚œ2„±á$_oG­Ús rŽªIžg+ÅÙ¸ó>ÿlÿŠ¢Rîã—PÊ‘4’8?ÊÆ´n¨ qÎGô0×<Ó+aq c¡ÕjþyÀrbå=~â ‹‘8·mR‘¨r¦¥KéQŠ…ÍŒÁ¡ZÓƒ©:1›¸ `GÙ‘ÏQÛétÐÓŸsIJ•ÙùnMž,c ®d¤pat …¿˜3DCŸÕ7·Áó]Ž¡€]ÓU¡è¸³ÛŠÃ¢§å‘Ëš8Aq}yV<’ùö(/^¿©uÍ7ö:FÏ}¢õAêÇ·VáˆW‰Ælù_[Óâß­ú%ì2u½±c`îô4£P5íǰé÷_3Ù²œíÀ) Énµœ¢Ó0cÙç ùfn¦¿Lº89A—ëû¼F_å§¶„Ç6›·t9+;,ª†B»Íôì뜹uGK)unc­&ÒH¥Øp*©ýŽãg!8”ßhªûhtñÚ$pÉeZ¿DK†vˆÈüü®`o‘2Í0 Ö3±Oè¬ëÕå›bQ´Cäêïú±b>&p£SP˜7¦®r ²éñ»C볊ƒHÓëDèãå ¥aRh/‰ðVfX% <¬ªv·ÏÅ^'YÍi,ÍP°nNž«1ÖÍ-û¨yÿ Hš–5ëÚvïWRŠ`¬Ä­ñI%Øòm5ú&?œq»Ä+¸Óqб«*NY–=ŸéþD7ëè縦ñÉäS½Ê"ï“mø’U °CXîí³À; §‘KwA&_gOfÏeY¬°DB?cq¿¥š=Ìôµö1ñô/7 MoŒN‹¹p³‰ëç–µ²%˜ð2ù.&¥Å‚m»ƒ2æ›WæÛ-PvÑ·Q*‡«ÕŽÏQÉiÆŠ¤(W`è,Ó Òñv¥¤rz£Xû<³vYz++жǂî s_£ *±Ë©Ü[­„%>ÂAÏSÃK;Ä’,äÀ÷€P:’ÖŽ•rèBÒ3H¯_ªÛ½›dÖ8¡©J&ÕÉ9^¢šD6/åxåÕQkàµ&‘K„xÞþ˜F¿Ð7AØ2ž5R´œèÞ("fïÑmÄ4Lÿ¸Nnžžz¶"íáÊ;ðì1AלpfmÌÕ5Ré ò!RY(éô©b™7ºÓ„Ìgâž«“Ÿ´ãÚº:_Ìd„.ѾòjEß—o? ¶°äñO’üȳZ¸Ódü<Ä3ü\Z '„G~ú粈<ïvï‹yÅñâ]S¼×qÆÂ*I#tÒÍè6•›S,å§9‘Ù¡h%ðkA»-Iì›6ª+5LJ+ÏŸQƒy1&"óX>R°¿'´Üjé›~<’úqTnܳŽW'Òì À§àY¬ÍXðÐTüÜ«´ä#\ã £]É7WŠþÚ§þº.ž±×ž86SåÓ·ªç]E-ø¼† xªæÝ¼Dø—$œù Q¡zûé]Ã>y/»Þ7$bÝt­K£:åñ¸'ÕònZn1(ÃüF@ØÇü;Úü4)ŒøÉÔ- ^5‘¦Ÿƒö‚·—cHú/‹&ø6|ýºì¿z§©d|ËÙ}½®§©:›ÍsàøF‚ìE©dIÞ{ÖŽ8òg¼Ï[ŸÝ>@ѱæéµßg Ê´&ú»jÙå‚ÓŽqðÇ b«çÙ,ÒÔVÈ©íy¾×e•{$þ¸k9\WkF2þ.Ö-¼ß;Œ§Ü¿ ôb¿²TGC|$¹ê59·=²$¶†iÑÐ…ê½æÅ(Ûé…áQÞDª©•É,è:ó§Ž£ùµÎCÑE‘rmtÖ¸tBÌ ö­d|kƒeýåìѾÔÕÞ²IÁñB+_÷6G¦öv!ËÔÚäžK&›"äÕ|Æk§öÞ:«jÔ8dŒð$¬o¸åÍ_3à´—ûi{¾²ÿd¼½«Gb+>ïz4n°Zû˜ lGõ§AÍÖÖ©C:é*”NpB¡°ÄÑ´tX“é¿r.-mž´Pp±Ø™o³H§åÚãáw»K»×ª#afiê¿gsRû c¡‚&÷©mU9¿õkS?ÿÆóÃÇ ãYEeÕ÷efúî¹÷‚ªÿ’ûÒ)!#eϼ`{oJPè*ÑÐÌ…¹ñ€xI63°%’äƒwâ+g%™ºŠ”ÆÖÇ×ê.à3ìqšR³Š” Î ü…ôïº"SëY\Ÿxýè[˜Ž_nÄ UKd¿ód%’™ oÞ<Ömo±}ôÃH+¾êß‹/áž•Âþtj¹-k=z'Mþµ2¦ÑV¤N‹ùBbÏZ¡v¯áSôÆkÂ"¼º®ÜCÏ¢E©ÎëÀ·I¹ãÝ“OâïÂÐhÁ {ö¶J¢KòG{n#p§pÞc¯\Þ¤ÅTî}Œ_ížÓN5[•}êM½Åðæød0Uþ‹"2xë{-ÏrTì‡ß¨ºýöó#×$¼t!wô¾o÷¢QåܵB¡Ù¢ÓaCÐn™ïÃ×TO'àøæÞ *^5–Gm¶«?2¡¹±|MJè´él3¤©v-lñU+Ý_ËÈhX±+,­~0±8c2è¥yßSZÂZÃ{œÿ^Úl:+^.p=i¥7Zgù£Ùú¶0ÏmÌ••Û³Ùq ô¨û“¡Ž-¢ï›Â1”Þ‹bø´¡™dJDÞe¶òCd¡À õº ÜøZ"U}”&#„>Q™ÈÂÙ¶¦tßaUb‹&Hµ•-­–i^Å9J0Ó,´þÞßóyÝyæ¶Ùl]b~LÎ9ÎõÀ2¯@ûd=6Ž®@¨0—_>ŽOª³x¢ü‘bä|?1f8†ôksWr÷È\Ë̪—¾^Ó§j~þ­Ç™uïÇð´UÝ7€ÈT 4Žôëo÷š0?îö%à2“9J;‡$[)ÎÒžÙq2bž°{ÚÕ°s97ëkéhÛ5™ƒx¼Öç~Ú#z4Š•E6’]¹ ¾í#û²zãþ·¤²Ü—°íÜ”$gö좸ÔOõ,0,¦*mÉ›¤“²æ>ÈŒDñÉü‘¨'»[­Z'ç3B×ÕÙá@¡±Øè# zþª0å¶ŽŸôòùoé·Å\ð)]ÚèÚ³šÕN+K½ý ëc© ÜæjÓUZöìZ QLÌÝuaF±óê”c•€tøÃþ,¯W@=á"ƪBvxdY®Ëm>Üæe`šGT/MÛ^}µB“ñX_Ò?Û^òBX‹g^x Q!üÞÞ ´¾»#X'AgøGŒpûjÖk«zž *¨cÆóªûUÙòÀ¹kaJAõ× ûŒdF$Ïzýéiä<à‘Ý5Ç-xes_'еô¬¥`¹Çwi•£”5‡¡LXu84’€:Wù» ¯Ÿoê^ŸüÑÇÉë6ì0‘§ª®hÕ7Ïãtû¶…ªVà`æL&[mš¬yÂvB#Ç$$^áΰÕíòeD272çLoIµt”­XO{Š^:]nŸ{Ë@úcÖ°LûÐÜÐ&¼ãåi/Æïúx«G¹‹:Ö£ÍÊ4¶xŧ¯jˆ™‹4Úëߺº_˜Ç®Åæ=Ë¢è¡*ÄxlLÛ/Âñ =5 F¨Zºflõp¬»<Ðe.§r¸ßútpW,‡*kÁˆ%oÿX‰ß°Ú÷½ZŠH¢=}GB«z­£1á鿳Þ“¡ÐkK·×mø¶ATÅÿ*žÆÌ*}ødìbð"ÔuÌj ËÙÎ÷C“2-/ØÛ^ሹ¬ž b§[3N~›w\bqgxûU!Ý.Boh0¯ùÃ!gÝ=Ãj “óµ¨W6\<~kÊröRÞû—2_¹¨?΋ižÉ¯|06Ū{t$w}ùa ‰ìQvÕõ%?4ôâ£s %¹¸“Ú†^©DQRoA%BÚîúÁÖ}BÅk,èƒSûÊñÃÀÑõ×ö0´æ ’+má±rÊÑí“ÕïjLÃÛ|©Ó˜šø`%Œ‡}DñDa$ºïB\Tw5ׂ/EÔÂAÎiª—ô–Y ³Õ›ëf»Æ‰ÓÊ7=íæ{&—ÈëLÒJœJBé½D°¨q* öÔýZª f'jÈ5®7ßÏíÛÿM'å endstream endobj 829 0 obj << /Length1 1531 /Length2 7808 /Length3 0 /Length 8819 /Filter /FlateDecode >> stream xÚ·T”ß-ŒtI‡ 1”tƒtwwç 3tHw7ÒHK‡ -]Ò¡tˆHJ—\ô×ÿï[ëÞ5kͼûɳÏÙÏYïÐQ©k±JXÁ,@²0¨++'‡ @JE““ÀÁÁÍÆÁÁ…NG§ v…€þ4£Ó邜]À0¨à¿¤œA@×G›4Ðõ1N(ºAœÜΗ‚œ|‚.¿a΂i ;Ø  ÂP„AA.ètR0G/g°­ëc›¿ –ŒN>–ßé 3ب]mA-€Ì rõúO a[WWGAvv6 ƒ ÌÙF”‘àvµh‚\@Îî +À/ÂU èflètm[°Ëv-˜µ«Ðx4@À– ¨Ëc†Ô ä xlÐRP¨9‚ +ÿÀøsoœlœ—û3ûW!0ôw2ÐÒæà„z¡6k0P“Ufsõte¡V¿Øc>І-~¯•Ð þIÏÅÒìèêÂæ†ü¢Èþ«Ìã.Ë@­¤` ¨« ú¯õIƒA–ÛîÅþÇÉÚCaPï?5jeý‹„•›#»ìäRþ3äÑ„þÍä àåàààà€œ OK[ö_åµ½A¿œ¿Ì |½aŽëG _°5èñÝÛè¸:»|½ÿíø/BçäX-] 0ýŸêfõøñðÁž#ŽGíq8~}þ~2y”— ñú'ü÷ù²+è©È(2ÿÁøoŸ¤$ÌàÍÊÍ `åâåððøx¾ÿ­ò7ÿ¿¸ÿ¶ªÁ®ãŸ‚ Pk@à {÷ ÷?UÁðçÄ0þÛAö(e€áåsðrX>~qþ?ëÿwÊÿŸìUù¿)ÿ$ëüv3üöÿÜ@0ÄëÏ€G%»¹>N… ìq6 ÿªúc’U@V`7‡ÿõ*¸§Cjù{Á.²`O•:ØÕÒö ýu å!`(Hæþu×X998þÇ÷8o–ö÷‰ËãYývÇé¿-e –0«_sÇÅûtvz¡s<Ê‹‹—àÍù8 V Ïßʰ³Aa®)€Gz¾k˜3ú¯}É `—øeúø¸ì #~»ößH€Àüq>*”ô/økû/È`‡ü Øþœvè¿ €Ýñ_ð±‘Ûoø¦–nÎÎ7Ào->nÃ_ø÷uy‚,Ñç`–B!vu!®j$ž{°n‹LÓmë¥3²z/:·»Ý`¡¼f¬ÎZu¾x=ÔƒóeS†á\|‰òÞûûû”ðÖd¶[Ÿ;³DÍÉí6ô…ODýo¾KÔ÷‘£‘±j‹ïøÜ;ùèÚ#¼Ò©H—ï䯥^ˆåñQγ¾¯üóhØÜ¶ÆNõK%Œ»ò)ÖXãÀ’º‹œÙgÔÈ®¬ä¨LxÇžØ3çÓxy”ЉÌè¾û±ÜÅÞ†k\q׳¯–+µ¹\ºHhI Ÿ‘#œãN¾ð–ÜMU$ž÷.}ÓÂ6ÂUx¯˜c²‰¾ HÅ`ºÐëm7®Ô"½±õÂÖ>²sà‹ŒzüJöƒTjôŽ^¨œg·H«ƒ,e—ÍÇð¢ÓçjÖí@q²$“lðt”£cå}T¡s:ƒ ®any‚/‹›§Ö›îŽc›B™¾Hç^þFI\¬½Uõi±×rK…ù8HŸÕ3ø:°—³ºwÒDÍ£ÍP|h#Á‹Âr¾Š™“ÕVÙ¸Ð-.U‘‡_§ÙšŸô2”kO±<‰¡Ò®Ñ_O»ôµ±wÈ‘Ç#ÞJ”xî]uÏ.áq%z¦zpMÚóbSovïœ'p÷‚ÉsÃvêÃ*Ox#¹‚GªãÓá$á\iþ¹cn]â]÷ÌÉw÷ lw¡w°OË:u&*²½M,w«{­z1Á',Úõ³”¨æ+lÃÚÖÈÏ_Þà2XÝ)h À‰ 3–ÏÝýd !ëÒŠI¾ h`γŽ/iR' ;Èä0ú“M¯×c“Vö˜IÀ¡à÷yVË€ÉÙdlöL5~ÍŽTwù*„à`S[ý!»ÿpÉSF+>#å¬Ë·Ö&AÜú½*t+køöà=‹AO6¬&Žîƒi÷8­Â†oí`¾Î;v‚BøW;6_)ÚÕ÷_À\&¢[üD‰¼*3¡¬BXž…œ&÷cÜ''zGÉ ^G]c‹¸/²Š= À¸ÃóoA‰¶ÄÉ03Q$]}6×Þ ‚ƃž²à>ž§ZržÉE¤Ú<—±²> Ž*ty–3+½‚Š3ÁêíeúZ£• eÓ ›2À#AKÆ S°}7݇T°Ëô á¹ì+3üáëñÛµÿª;:á´x½jÙv“0…š‰³¾ç×/q'£Ç]<¨&RäŸá©1 ¨ OQÃ׸KâÇœ¿ë[e´.I…šøZMÆGJ.Õ“‚¶Có¸Sæðåí„Rb\ÝÈ$TC´| ·BýË Ÿ™¾yÒ†çÍŸ¤›¨4Sª1[ä–@"I e›lšÆ~Œ µ/ŒÓ©÷9{S3‹Xv{õêˆ e¡k#W0Ï¿=ht?ÁœŒ—ë­út3wÖ‰¸«|(éÙ'WûnñÜ\>knGcéCT¬ J£û ìòZVÃq‡ïRòœâÏeÕD10NµéMj›§8RG––4çð17Ìæ»£gå$Ú/±°‹Š‡Ú^—z”èh÷¬ôoºRýð™·dFab™¼_ÀÖ·õâ­ð·ä¦+ƵÍ85 ±ÎÄT.o`»y… dUú$°P„Æ”*ÔV÷ÈÚ a^j’óÎ-ÉWîû$À¯Q.÷¨{¶™ ûƒõ²9”F¤Ã´3*0ê—Bä>œ~Ñž >JÛ²¿Bæ›ïa-xû³ ág£šu–$c-‚Τ”µ ?[ýS=™·‡¡)»hø’µ—Qc¡’øš$Ž4¶mËȸX{Jf«áç*g‹>:ÒQ+³ÑLcL}‹ÇÝSêž¹5Î{„ëÑüìúÃÚ$„|íš!’ìn˜Wú\—~zúѵ€Ö`ÓK[iðÞ†îNP6¥¶P©ÑngÅ즄B‡R1¾çIÍ-âJE›î9ÂÈ Xsý¨±ÿ§_ÑÈèBŒÀ ýsdã’æ²\¬% Çñ½ÊDE^ÞŠd›W| 6ròUR q‹Ó·K ¡l¬òÂk$¨c$Ø‘ümÒŠ+‹† õþr3žÄj/Ú‚B‡ú ú7EÖpûïæ%öžz¡´>ëšÊ:|‰): ¡ ¼¹¹BŽ)É´e»8ºÝ–~ËÀQúl™G\_$`’ÛòGÛÃ2ÝHÃ6ª=uÏ•ì\~›%¾Ç«vÖ–‡×ÆôEL‰kpºÏà4;7¸oóÏ é¿¹!Æjláöí…=(=S©Ï¶B·Íhï¨}Òâ–é¢mpg«P´æOájbµÜ#ü“‡¿êÓyùy|´ÈÏ¢÷¹nïõÇE4a§3æ%(_WrÞé^Ï’›Óⳋ¾j²à[̽§·ûª@‚ÌI Þ†íòÜNnöt°-Mr½a׫*¢WÕ©Ø ¥Ž:]J eæ‘a,gbTO[4*²40Íi-Ã^x|È6H"J‚hèÍx1݃Yp\à[Î,e?óeÅ[ãv˜Ÿ”’íÁ²_FköTš±ã°ì¬ú™¹jÂbbe .ó>g€DÖ=¦ŸD¿{0{ß„JZ 㙉);‘Z²èØî´–¢³´ L9k¹µÿ¦ñZŸ¼“]øªÝ³i[ÿA*3¯Eå0\_y“ºK´,}¹]<:Ø„¢âÁkf0äô&¥òÚF¼ÒjgѪ9Ù6ažŸVA=îkò,7)$ÊóM—ý"—WÞÁñü‹èÐ%®m×vH?4J´æNèÆk¥fz—(ø*wÅGjuTÝØ*e®î&—ò0($?LÙ«ŠNÃÏc+©¤&æãȃ¤ÙéND´NÕnY<‡»Uùü{?ë¦{~Ã^nII t^VÅ®µƒÙ#JD4µ6fPNĆ&„¯59|–ù²¦ Èü«×ß7x€J>¾>õàžÔÎ_×Yç’ÃGœöTøJ©ætnüz±ê‹y(Æ•Öd&„4;ƒ¯ø¥—Šˆñ %ZŸOóô¬mc‹å‡¢pÙšµ0W~\´c0•#óVs'b«pmn©ÆwôŽž³M‘^…O¼åFïuö¹¶J/ÝcدôӢ¾e(¸k$gౚ6~eëbü,bl£žý¦2¥ùÄ‹q¿‡­‰ 3B̨æ“îSòçhêÈ€%?Ì(ÈøçªWÊøéã‚·.%–íG2ÈÛi"}^è>p†j$ÌkïF·˜¤@…™f4¹¢n¾éˆ_l×Ë4Òñrïðo¨ˆµ¦¤|ŒŽ(Ú=«æ…ec>ܸ:îwÃØM/ŵ´˜âkz$AÑŒOAþäë.ü&Àv¸o’“,ùñFY¼îoëA`lºŒä™ûgpu!¼ ƒ/Äi×?1¼Ø¶»áqf¬Iu‹fI‘[Ö8KЃ éÖ)òô#ð¼9Ñ­fiÅ3©ã™úÔâ9¾)‚–J“›ƒzºUs4žÛ¯Uì…éç¡@Z/ ¼ÄrÖJG;TÊïHÜY7—L«@ÅS¬ÏQ›ÓÄÄt1c!rFÔ9cRB´]þ¥Èå®Hû SÅxèIS¼Ma+Ú§]Ö×-g™–£Òá mˆ’¨Ó…—FìR‰—vxjb´TY0üÆê.D'o–ŸË¹" ¯Z"éOî­üT´m]…Ö\SÑÛ„K†^BTp^ z_°5[b±ûgxq¢/ƒÍ.fç:6¸^‹ŽÞ/ὬÏÉÚ:/…Çõ â=oË1yQO’š¢âW9>Õe`õ…DU>¥9Íýiº»(ÃD•]3YJ÷vQ_ç´të6T‡S®)Oã$jb°Lö˽ªØÞÀ½¥¹B“ѬûÓkKm¡±WvcúM`&9"ÊÃ`Âæ]ht+r¸õÃqº}•Nƒ¸as %â8§•«5é ®Ú±­¹Ù±ñKeÆŒyV"ÅbÕwÄI¥ÍõI¼Ó¤*(²€ÊÇéÌÃb+´¹/M÷-ˆ¶A»ú5¥^×4ÙO&w"‘Ÿ×UÊ(ÌêJò¥*½y¬Õ pþô’_Vâpa9†±©n4s|.w®J½Ẽi×ýŒ²Œ‚H·©¹â‹Q8ž5!¯éÒ‡ú<ìÇÈ¿Öa–­â¥”„§X"¾«jB>C@•hý8›†®IXœé7(Ð&¥Õ¦ÒUÛzþU d k IQž `pR˜TNM‡ÇΪêC½ÿ4Ù¶±ú:¸»¹‚{C0M½)mPµ€/ížË¦¢¼¯J³Ž·â”JÚJùñ<æ(Dlvf~fÞ6µN±ñUðý‡ðh 顟ÜöÞ=¥r4Ëí¶t×`A󳋯äS¿˜Ãg!&19ÑñÉ8•¬ Æ9Ð’ öX ùŒDk÷°¢sHÏáõ3`K©·‹lg^`BN„¥ï©Ý„>Úv ¹ëF|ò`( ¾ fPa{â‘í Ã9}|kð6ØM\éÇ»÷Z9Ö§ûšûv#ÕKdõl°=¾`öÎÝ0YF ¹5rÈfý‰Â³oØÖ1ßNõ'¹6Þ±; 4Ù7¬Õ탞3XyÔ2‰iX†UH·éO7º1µžFsœ©f—N"K‰5¾_Sõà d!n´’îWI\ß=÷ù€Á§í6lm¡Wee¹YòÐUrð9jÿ©z [ÊðÌeõ²œTþG"HQ ŸÆ{‡Šnøz¤ú1.Ã|ã}ú Ë!Õ2ûÌ®` åÓQ$«yé÷€\±Jcu¤/IžŸá tPƒ‘¹a q*p˜ip9ß'>ºÔˆhßžœ²ÐœÍF)k®±¿- G·Kd[n< ¹™ÃpìÍŠ÷\Ýð¬ÐŠuðÀ·;(Ý|áÏ2‹cÛØKù(êÕÜ`bxFPÆeYÃi*Ãij–PéA«]ìC¼Ó°Ç ÅôPNºÛ‘ˆËk¹Pt?gÜIwÕOÑšÍz¾ÓzÅÞ¿EëÑ—&[E`°Ž‘ƒëÿ~U˜‘æ·aKý5©®S÷R°Ñ¬ŽŽÐy¹úKN´Í÷EQ$î_׆›yRP(;©Ý”P ¶Þ œóL| …Bó£)êAÑ€ÂÍ«<ÑœT¼ç›cZ§å¼ô¥DãÇ™€žÊœLÝLî/Ðôiûš±Tó3;—ŠÃqÛ­çtÊj® ¨$š韡 ˆd9oÖÜÈlÕyŒ5SThŠèü6h¾õE£ÂW;>*’,ë5$mË48ë2Â0_SH.%^ÀŽ6ù¢‚)´)Jû“Vãie0û§oYr-„€Óôç$Ïbêø; #ÑÑ­ÍLCß6÷hÐVH(οØ&"YÜetÚk}gËÚz¥÷À.’Úf t~ÕôÆ+•âþe~ÅËD²¨ÔÑÇÕ."³ž”~f²z‘KÍÆ{âyk8u§IœQó ªJ‹wÁÓ¾y)Ð6Ù°x—ûÑ·ÊZÀeèˆÞœºѲªûjΈ«×IÁgªOâÅí!iÐ’Ac\%߈ §Ì!ž—Õ—PôÖWƾ¹›ñ…jF[ ?d‡çfßë1öð4 ‹Ä“ì.÷Éû‡©$é”±X2rlE0çõIöG®ž‘dú®Ugü m{J›78ixX—:¦¶Ë–n¹.§aPŒ§GðýÔ#r(IAe~wÂxPÔaý¨ÆsxëyŠmÙPüú–[<í°tXÕoÆ2(•U=Žåµ-FÙ¯Eƒ5ÙŒ e SäþþFÞnB7¶¢€¡îÇM!D6œ’¹G×^ðnŒ•/³%¥;_È gž]òÂ\¨."«ùÊÜa½Ô]ä9Ð1cëb D£\+¤ "MhÍ—¤Õ?ˆNðÛC¢AW±À× ‘8¼Œ–}ÆÏvµó‚ÓR,Œ&‹˜*ꋤríÙÏþEâûùpÁa$9~èMƒ´SÊÆwä;•"üò}E œñÌw¦ÚYÓ˜½vÖ?>V hÏKÚé9•i&p…ÍY‰ò:Ö‹éȱܜ©á¯äAž·Äò¤,HU=Ï¢ß41ìåiè*”vJ84°×o¹f¤“Í@bLG]îùŸÍÕ]OxùuŽW$O‰Âj 8z±ófoÜý±}|*Vê®o&l­ÎÄWÊ/./ A3ÚR¸/"òÓÊcÂJB¿7yglFK|@ÖrЫßI 0᥎¾w–q_ÜŽ ¹a [²=)Èþ¨ÝÑÆQÔojÈh'WŒôK»á‘Œ8q,cN÷²/²&\b :ðË­v¢Ò 5àÁ=dîpy•êð .ø ³œú8¿V¾¦B¬!²ܱa¿1B—qþ*k *ÞýXS)ÿbOVz! c-Õ¼V•rŽ-þAª+þË…ašèkS%´³µZ¹JxÂ( ”Ê¥Ëಷªóä=*Eõ¢5Üq>”LëÝÐÊADzðFì4ŽfÈl_ í¨Èþ֘aèÓÂΪ?B Å8îHu9zˆjáƒÎdZ²E:t!\ØM‰jíZõÚÃÙ¼•ig"º—.›F`Æ{Äb«75•ïqûY›ÙÑÀ@uÐRˆÁ³Æ|‰W6ßGDž¶ -‹¸„>þÀè¸Zøª;S+€ýÑáðMò’Lx͇ùçrQOÇu˜²ô!!ßDyë;ãØ €¬CðïJBsnÝžÜ} ß¹ò²÷?ºøñ"O©|æ$ÐY +†çcœêDËùಈi­:÷˜Su ìó‘¥xJkÁ}öÕ†…tæóÊÉ9ïäQ‰-4•ר,#Ä$z)Ó]Ô4pj#¨¬øìÕ&ŸƒB(ù³íWKÞ¡ .ºŽ@Nðä{@š?ˆxÙbüz§rFy¸_ô—(7„¾†lv.ªFQžG`÷S7 "99*öÍðÔMøÞÅ'J‹iKú¸crŸá¥æ+³Õ ³¤ ªo3Âh¾\.—•-Á–$ºñuü @áã¢æF©éXb­ÉßiÞá±{ï*pÖ¢L£›¬™'À»ºé0¤5åSšÊû˜‚½M­ð­–GãùB­Ø c¾qé-]Š©££[J´;ìC>w0 „Ysw”l?q°ç{#ò‰»Ã²®x‡è“Ãȉ`¯DŠ×P´:ÝKvbÂVø¸ÜÃ\­±§8¨ötŒQüX;ì²jÒúôA°ë8ê—϶…ŽéÌlœsTÂ’T¸£&ÖÛÆÒº¤ô{Ôjìê¬É2îqõ¦ Å!ìc}£H0h×x™N]í³tƒÞ¾cþz}é˽sîÔ÷{9[‹ø‡KíÙD‡kúܳ@*ç!48ìÝÅI|igÿ"$ãÐI§.>n3ðˆ5I)“Z»·F\½”sÿ’òq®ÅMö ûT½C.K)­k° °)ç4 ¹aþ¡(+*Ê´lE¨K°FcçÁ¨m †Õ¸ò©»ƒÇæç­^Ô¬”C­„sÐû#-2ííil6.²òøkZð„¿üâZMGrÁö×!kù7e²«ºéýô¹»v.¬1qøð Mlƒè‡9uýh…(H²ÜhÃIDSáM¬õ28›Q~‡¿]|ö .þ'–ã—Ò°Užá×Dï:Àâ[8÷ Ï+€5Ý®_wÊÜ3;`œa_ÜiS|ÒÓ3Ox(õ©ñF,Æ·¥Ú HŠFÀ)£‚[?|J‚ahøÖk|µ¥¥‚7›’•·Ìo·^ >÷ž :ža^Ýæ"YŸ:°~.bèïÛgêl(‹<¤P¯7¯Äwø6ÑFà®—ä4õÌfACN0K%â®_‚{]Û#›Ð!Eš Ã@ª õ$…eŒ¡‘}}ýó$ó9½8ÅaSl¼J } JðÙ­.w° ³681o¿ßzm¶³ä’çR¶ª–w1êLUÒ™ôžÆqÓÅ#â­תéA2Ú-bñü₞ü}4KÓ)b¡ë\4Áx …xwý¶éšåñøžÕ^çaÌš)‰ËÛG)Q\Ú%ùì×C£¥\> ö®UóK¥\wÌÕ ÅñöbAUýtc@Bën8¶{NÍ-aþ>_ý*åü«¿î—&oÄ3à %žP«g˜/Q,)Zú=%×z'<Ä’ˆ‰Á‹†p‰wl F#Þ×9AôƒÅ¤ÌlЗÙ=(ˆ®»U¨B›ZŒáÉ)ãø³~g ‡7':˜€$ìtäÖb ¤2ßy4{…—oøFéIÞµV½WykáŠ]4ZKö¹ÿæ;ªúØÃô÷±Y½¤ädnns;<#J=hú ý}pTôîiÆ pn\ý„¬ÉÍÒù,ñ¡•8zósÓ÷¾@^`‹õôÉT–ÊãbS­ÀõéOûè¼9q”½«w2wñö™ i ª*×lpS¢¢¾{¡St¥Z ¸0Ó&õŒgïÉÛRše# †©èЍB@RïcbØ£QCkŠGz¼`a›qsŠ6„rĸl“ Áîn@$¼öQ§-HÜâv9ƒdöNè¹8Ÿß7>ôýk ,ðûN6/NݾZʼ(ÙV— Ñ4:}˜r žÃLÉÍ:`ÅaYNwgæ"ó*ÖÒïø Õ±®m3‘'Ћ=:šOÞŠQoTJǵôž¶d¹U¥÷vu¬ÿ®Ó·!i{Y*ÞQE‚EÃ.²6Ìûr²çƒ®»ÔŒ?<´‡y·YQh W—п¸‹á#-šðƒ'3+0—8è((£ü:k6"=NrJY{Qcß8Ìëóä†{¹WŒÚXYíp¥°Ù:Šp¤®g)UH8ÅSK˜x"åË’¸ßªt‹ª˜íjÉ: X©³8ôÒZ¢óV¿bõSi¨ /½„@!Ç@h¥¾“›¾¹ØºOS‘œ!¯„£ÝoÀÇ`¸­Å¡Y[šþÞsÙqHö<Öºs™I€°ÜÏC9ù¦~þÐsÂïxØf~ñ[©bÙZCcb¯â+/>ì×Uç%2Ÿ§°ËÞ¥¶b?HZy„{®N ŒÁh2¼BC´‚K^¡®ª«Â¡¯" EÄ ÈŸV™´qD_‹¢èÇ}?ÇÅ[uö‘5Ö*éèâ³÷:u’aÜn+ÒOÃi–÷ÚBåúÖu¡U,O@ÖÊj##„%0`ƒ«,QOhl¿)vØzXî“ÒÝæìS¹(:B‡¼;¦_wÓ¥4&~›šÃTL”‘|:¾[\æòySy:q愦NÍ„ûçÍõÉä.:Ó¡ýtL¶”¹N>.FãCºÌ¤Ùc'-¸Ë™LoÌšU2¶Ïá*ò‚¨ð>NØ.¨â8‘Ü-÷ªLß2hˆß'>Õ0‡hÞ#o‹ïì0}(Ïýö]z<‹¨‘Þ¶TTEPŽÇš0~þòd—>.tg=$ÍÇß±¢Þ¾ Ô?ÝÚMU„à„!)$Ð>…]\“ÿäqky»{Ì”]ÇÊØÈ+YLÓ¹±àið7ãÙ¤D}5^Ó=a­ô-Â*ŸÐš1²g4XÇž©<^O,¯îI¡ŽU vϾ¥ÆgͰË»8¾n];˶Ðþ€çm«žŒ õ Ï¿ƒÖ¶ÙŽh7ð\ÓŽ²ÛuµÃ²Û*X vd]«oƒe4 .É}1®Q2“¯´@²$›áf*é±| YÝÄ»õ³xÎûg}É““ýyÊ4Fä|JÿÆž ø endstream endobj 830 0 obj << /Length1 1477 /Length2 7062 /Length3 0 /Length 8056 /Filter /FlateDecode >> stream xÚwT\·6 €H£ÀH7Cww7H  030 ÝÝH—´tƒ´´¤H—4HI wô­ïýþ­{׬5sö³ãœçìgŸµ†ñ‰¶§Œ Ì ¬ƒ"8y¸€¢9 ]AÈÇòâ22êCŽà?P\FC0܃Šþ‡_!˜< Ó€AªnŽ> ((àEþ „ÁEò wˆ @ƒ   ƒ‚]qå`Î^pˆ=¹Ë_K‹5+€GDDˆãw:@Æ ‡Xƒ  Âì„ÜÑäЃYCÀ¯•`·G œE¹¹=<<¸@N®\0¸$+À‚°è‚]Ápw° à]€&È ü›.#@ßâú¬³Ex€à`p„Xƒ¡®È7¨ @î ÐSQh9ƒ¡«ÿÀøój<\<—û3ûW!ôw2ÈÚæä ‚zA v[ˆ# ¥¨Î…ðDp@P›_ GW2ä‚8‚¬¿(Êè@H~²sµ†Cœ®\®Ç_ ¹•A^²ÔFæä†"\qO[#oÝ‹ûw[ 0¨Ïk[ÔÆö7gn(ÄÅ ¬"ÿgÂý³#@ PHXv€=­í¹×÷rÿvòü‚‘ç÷óq†9l‘À~[0ò×Çä àn`?ŸÿtüÛÂåáØ@¬+°ŠûOu$ ¶ýÃFvñ˜‘Âã}þ^™#µeƒ:zýþ»¹ÜÚOå4”•ÙþÛ%+ óøpòœ¼@@¹ðûw•¿ùÿÅý7ª ‚üy6à?U ¶0€Èw÷ ÷?5Áò縰þ½ƒ& ©c0€åÙ›€ÖÈ/žÿ³ø§üÿ4ÿ«Êÿ"ûÿ>¢›£ão/Ë/÷ÿã9A½þô#Uì†@N„ 9Ðÿ5ÿ1Ä`ˆ›Ó{U ädÈ@íÿ¾Dˆ«"Äl£ AXÛÿ! ¿z€,a®_Ï €“ü/rÖ¬O‰+²S¿]`ä(ý{K¨5Ìæ×Ìñ @p8È Ùx¤%ðáA§ Øó·®Ü\P™@ÒóØÂ฿ú)(à–ùý¶øÜ¶¤¬ÿx‘Ì þ7À/àF>nÿð¸]‘âýÛæp#ìáàÿˆ"Øoû_G·vƒÃ‘ãü[ZH^Ù¿ß0Øl»8³ }ÞÚqQ'óȃss\b†qÓ(ƒ•ÓgÞévE€•ÊZ›¼ÿ!“:Ò÷`å³Ë™ôíÏ^[#VD{²Î›Ÿ¾×‰ºS›op?L’ Níɼ ÆyÌ©/½å{ãâkäp¯ µ[•1ßÅM˜@»øÂ£_Éóõ@ÅòûðùM­ZA5¼ëŠiÎ8ƒX³ ÒYÆ«œ9 :L'56ÛÃ#OÂÙ³3ó&îhUÙqýöãøŠ}L6xã/ç¼W«ôy]{((M(¨ï=|?Åä#»¦J¾àSV¼Ÿ>GÖ9öÑ)…Çq›Å{SS÷¾sòŒ‰qB”…’‚û‰JLìz»r’Sé“$Lþœ£ÕuO•¡6+W­$È–£PzÕLÉ“-+’ÇdÏöÖ·¦Ç9w$ øJbJX±â›bŽÇ¢oq.еôR~ÔcÓ’z+Ò‘?±¾øq#ý´îaÞE,íÔcÎÛŒŸå˜/; auWcÄ|«B ž‹r3°Hr4‚`hw›Ãecw9º-…Ð%¡.œ§Ê‰ÈDÞ\è]{›–§’ŪÙ'½Qâ:/¥ì3õÜÓ›”¬ðM*á+»—û¼:˜~¢;o‹lù^Éqßåçç5¾§ú9;’èx*¹?Nîh•ײ'0^Ýol•pã ™ü86áœÜP¹MçTæ¦ëì”zˆ¥…“rå}E—e}Ûw& Û§GÕÓ¾™+[­¼ï=—j´"Ü<»’ì”¶¹}Q1E÷™4¡G ª# :[‡^×_×Bøï¾ÏJ–;{1¡á˹{YåZ¾ž¡*yŠ>*âýy|Ì ˆç¶•c%¦X!Ì¢­hŒæ»@"¯Ç˜ä%qn}¢d’1™‘[W¡)‹ ÿ±U]– Ìþ$dy–·ea"~Ll—slÒ}³76ö°±"Œ¹ž—0—ì’ÉíùœÙTgçш‡ǰZu`Ê)Ìi^RC¸Q¬^ˆ–{Jrº™&!ÂÈ”Äî'whÕé®®ô4í¢¯ã±Š\wÇ„wpZzE „ƒyžgBç8SèY2_»BÛÅLÅá~@ µý“â9/sGM<üA>‘DEVÖ;ÉXbµ@Æ÷Ó Pd'³›Û%Öí›Ì’Œ„ÝâßÀ\=*’·u ‚X³[„cj†AÑŸdž†Ü%=ãúG•ƒ;, ïýQ‚2cü(iïVbôYï”r¢…ªîO«uPEòvÙæTËå~€•Hxܤ‚CÈçø£˜ÒÌ÷¾.eÔÚŒÝ)®8;ícµ<¬%´oÍŸiÈë¥dð(6«UµÁfïÑËW(íyum5LdœY–š®ÏSzgÊûV~‚uùÛô ÌD¿Ýñ¸&Ö}Fç»yF¸Ãì$ô) fb×P³5z4i‚ø³Ùv­1E•{E-ºr™_Õ®8ÑlÏžwœ¤¯xc½i)˜š¤Ydïí_ÛŽueß`K¦4àÌ®¥]'4ë¿ayÜ+!ojÃ*}½ÆˆŽJÈæ˜_µ/{â0øbqOÎV!;HàJÑGü -ÝÏ»þ¸C3â¼6FÎ ö‚+ËJáÕÒbomL Ž©†iЭ=òÌûnÄL±qd'ƒš¸ÁpϽÇe’8Y‚Lº íEbáQ:¹SÚè]ÕæÜ+˜½>µK ŽV¨‘vã” Aƒ«‹¶cü2 ±#»rŠa2¿:ð0üýÑ o‰`[¦/íffÂð ¥$*é-–ý¶.@~ÒˆV ¦æÄ>‰/Ø|Å¡³Vè*¥v r°CÀÕÃ7å2µ¨_òýr\—ž°~%…PbZÙ›ˆ:vïÔNßWÌšEçfþ^ÛmV°×kÈõ:ûÌÌáiµ#ÿm :ûÃWƒcT‚Ų͹^g­—xõ ßõ¦kzÊ›å‰Ó÷±ã›?xŽgRï¢G˜šøÏ§”~ ëÊt–ºønÕ"(’${®XÆA¡/: ï5Ä4ž_Iú¹‡xŒßw/ò‡F€»µ$/™}_ðë\ƒ¡„s‡¯BæäþròäJk·‹®Œ—8D”%ŸQn¯}í°\Ò"}8fv–cZyŠ»r…HÞ •ØŽ3Ð8†šÊZó¦YÜ‹#†ºeH©Osʼ¿õlE¡”póK¥wjN¤žñ”Á§ö|†¡cò“‘çÅ^›ùDô\  «ŒcÊfì•ÞÜ„ UAV7´…ÊG¼æ»¢œÝiJõ—Þ/èë²3¡\cÓ6¬<‰ª_¢°½hT$Ø)­m äh÷ÄðJé1û6[1Ö}¾½I/Ü×dB ŠJR(h½3VU=TŸ+J2‰O®Ø¹“Uæ|‚âïÕ1Mé<÷>zº õs~häÆ|­Í7|"oîÝ¢«u¾¢ç¤‰El=,Ôª¨Ú/˜k‹ªe¾è_4·<­ð¤k8µÊà÷ç7J0×¾•ÔuN!R#¢/Þ9›÷î¥Úî½WaÃy"d¦*>ÚW’!T!ºnÖL,d?f€+î9D ÇùybG>;|7žè~o,¹ºÐ­òÀFùD…¼`=Ï}yÔ`ašW•`û™Û}–ßôì´lgûacv{@9Œ´òIj¼_¢¥Åf‹Í³ëF" Ǟ–Ã3›v+i—MÅøöÝ€EÎ}𞇔òÎsÄ?Š|^…'âÛÕLHûU´‚v’é°'!Jå w\ChoK0kÍûFcK&aÁÔ»úϰ÷ü -çå ‚*Êvu0…yæˆÂЫ­GýfŽÕïÕ“ì­Ñö®­¸ *Ôüv ³n×äqÜò éÙ—w(D`XU}c×dYì¼õbŽ#Zút aá™tŽÓêDáǶsšlΜcŒì8Õ¬ŠóœÏRz™-{c²Øé– bo€‡Æ{ªÔâšn•ÈK$D xWK·>†½n“«»)¡ùž0§Œ÷©æg¾\BWÔÛaÇ7è]a¸ho'¦Äk³[Ä™TA-ðÇ O+ ¥É_ tVS(T^*¶zÁÄ€K·ÔGRkËÓËNÚ“’Tt£ôC©ƒWuø$ñúªOب.6É/õÈ¥K5¶„è…™æ÷9KJ/󽂠Wý"/×N/“§Zê”Bëõ׿fGB °NâžW¦c7B©×3¥ÒÚuâ#MÔv²‰Úá ªdOÑ œ¤è½)=Öß/w¸ð:{ +΀G:öe5ç#ï›iúG+Y^Љb¹Ùü‡u5ÇñEÈ„šé+>ù¿Ôˆ9;Ë^ѯï‘j”õ&=YÐkË/Ô!ið®,_0HìS¡¿wt:£-­šI€¦Ä9´ÐÑèÜô®Þü¸ÉÊG˜u Ññ«X¹:ËóQß!3VR1ËŒkÝ•ØÆ¨ïº¦–~Þ\.ÖÓ½iK%ŒÐû× ÚF‹E`ãÃãå) [ÆÙ"-*ÊxgùâU§SïaŒòù~óm¤á MóÅÞ=j)ìèž*¤†¸Xõ¢§§íXùNS ü£×Ɔ]ô—ŸÚ[³Ú4® ÌK.؆ ^‰|&ŠDG\RÐÖ>1+,€ ` ãY…¥©«ÓìÞÂPn )èó©×¹S,ÕX ý£,dY%ZA¼x;₊Pë|ž'›2mÞ 'u]‘ö«d¾ÙýÐÀ®ïÐ#©ÉX%\12»ŒtOàz€æ(#@š²5Øgw‚bk.õ\õnÐóe…×òÍ…1v3¢¼91Y‘ŠqDŒ_Ýæ,j¾¡ÌÈn{xœc³¬ÖŽ„g15<Ëú>œL£Yrf8±]¿œ[4!3,‹ïÀ΄Ö'=Â<1•îÚÞn!ÖŽ•YÕBírÆbQ~Óš#ú­ƒkQ”õ ˜ŒÆt ‡J Ýê1À¥yT‚éÛ3«½è4è××ÃéV»A/$CgPù–µ9TßlÁÄsOóƒñ.?Í›êq_ºwÉó9¤žšöL/°SqìU6Ì¿¥¡ à½‡­…÷Ÿq=‚ƒX™ùz ^“ˆûaãmsL"úýØëÂÞ9_ŽBw‰¶C¿ðlZ¹ÈŠìl/KAcm¶Ö­Ó÷’ák=ÂXŒ$>0~ëž­v-½cÙæ'62XØ‚{ÕæFŒv=Ö›úù'ÙkyÍå6èw’‘¼½mÏ4ŸôšjÎI§æ³™4ý Þ£··_QúJÏ+V+·Ú\ü³žßCîá‹ÚøDºÚAÓF/ùJÕaú1«€¾(“ÐHC6!€'Ñz†Ú±Ü˜øÉ¯Q÷ÀTAV:†'‰ýsÜe—MÂ]g°$íB/ÝÝÞF¢½W–„â´—$O|(£s”J&{ÁìÁ![,rÁ¯Ýdêú\Ð)'·õ­ÝLÓð.RŸÏK¼PÈÂ<žË£ä½ãgýÞPUGÊËn×9hŸ&+$áëMÌOXJ¼ô“ûý'T:À÷ŽÉ:t û0Žç§Ê0Úc-¿vTLøÁOÄáÉuÇŽrS‹/¿R`.hÒ— %Ä¿æ'H‘tç`×X;æÙýÚãìeñ¹6~¿xѼKM=Œ î¨:ŽHhµ+î2á‰|!æ¿aIrŒþ,áàRª­:âêá!ü’ýaYTŒu~ÍœŸöˆcOÜÍÓú«ú¢L=(dñÙ“òSu”†¨$º|7²\Ú—ŸpG²ý%Š'ä&ùBM»\<Â7¨+ÏU.¯ôµ>èàãê„Ü‘Òæ¦x­°+²õü”ì®b^XˆÄ§±Ç5 L_µäØ>s‡óéSÇëÏø¬ßuò‘ju-ßæX4ÇÅ‹ï‡ÎÈï³ã”Þ¡®Ù“®QE5ðÑ¿ &ÿ¸ áÚ=òP¦­›gèÀæ•g j¹)‘¨¬>¨œ¡QƒUå80ä ?,íf‹ÒœKÐ)â1a’P•ŸÓOÿ|½MDq?ŽÀ¯Ðn"5B>BÿÞúø,ÿáñÄKÚaÀ&hs+)ÖùÜ?Æ)ëÔ;±i_¥B|Ên»¨·éaséî›®Ú•t¿‘L|­“ë <¼æê  ( ±~óÁt¾tvýZ/Ujp¹ë#Ä3´+ØhÖ™¶¼í·^¶dÉw¨F®’r%üxbMI%?drü 7´íÎò`|·þ|=yÀ>ëg¾©8þ ¸Áº§Ï:N„!³Ûùá#›Ò†/Ïð›yÞ«ÔÔ®b©797@‘Î0i.Ü6ßk¹…ÕˆDQ.åÙÙ¹®<¹ÝžÚU÷gŽ{¾üc¹ðàvý¥d‘³ÞMÀCúä^7QÉN[Ë : Ù4則fW:Þ„·œÀ« ¸•ÔÊ ¡ŸãÒ¯¤ØÃ bæh&ö}¨©.À• l÷ãÌøí±K@ÿ³jg@ œcE6‰üÙ'Ñ{šªè$=ÅwÀïB2Ñë¥ðĹR?þüo™êí5£ð÷_-ç•MÚÏ%F|ò`o¹z|¾Ò3Wœ½vÓ ÚŽ×¯ß8y›:€nl÷]Åç­ºŒfÒ`ŽŸÕ½ÇàýpnE)|™Vs+·œy÷‘Þ Ê"—ÕäS>ñ ~ Yý"RgPË\³Ó´¶~­HÌo¶\„¶]. l}ÿ9K± ïEJÎÍò‘dÒ(ó–M Ô³C3=ò ßÁBfíeóÜëºBWz±Ž%ác‰¨¨¼ÅKªž~¾9¦?¾Ù9ÎB#Ä4ó–{¯}ÂI?26X¢¢sÆUK ÅEÝÛ} yLÑ"êm)ãðŽÇªá'2·tUmíppç8ºtÓjzi*Ýž{jäRÉ×2K¾piÚ=zÈ+uŒw°2³\=Q:µ}Z”»ƒ:–À:WÞsD´2z&p[úx±jÊP –˜µ®°.+r*HÆé©2:éOÞÛ<àìhr®81¹õåEgn™”XØ„Kì¤EÒ·ïéjñýTÅ :æÁoç¼£èÕ!ê#Èt§>Â~¡|ÚòØ-G—Ššê a=€ÅÓãç-¨’NOÄFOUþìDäþ«× Iüân=8ĨPõnl€Ñç§8lëé)tÕX±ý}^›8š1"fë‹'ïáËê4ù=ó¯ú‰¤Çbõ',=ŽK:ûߪ]J íŠt„¤E(`º7Ÿ|©£Í´mê\øéˆ±<’‹H­9ÈX¤¦ßÈ|)†9FVÌÁˆRªÀè)üJ¶ÀîfdJp–&j©¢ ÇÅkˆ83TXw nå¤I• +LÛ›E%½ðy½ #D­¯ìŒjgUŠvÑNב?æ°:>ÉÕÏ;Ä¥Êéc&gÝïÔXü¬dîí«Ф!ðÙ×<"‡ûçÊXŒ¤KG\ì«ÎWêGá4L ^–—a÷/„47Ê ¢Nš7ÏËÛT>mMù }n+ ^Á_3¶£§µ¶Ãˈ ¦{ƒ0£2yí$焆d+0q.jzÙÕ¡?hêê4šÜD«šÁ¸';h_ „¦ø4ñÕNúY~ö1ž–,oK¥OVM.oZÜn±R“òc½q€|o–­0ZO-°‰”{3w *÷®æ§éö$y‚ÕôâÝ ”3¦A_³ð¨ŠFíf˜A©§¾¤ÌŽÊɲ½ÕžF¬¬a—æs¶ÕÅ“)¯Ä˜»ú[·7ÙµÎ&ö÷^ï#,m·'»éì;{œšwWZÇ n­U£?O H½j´=:g±‰ø"M VФ3ôï¨xë“#|31p`zsÒáDÐCÔ%G¿7éH–]W—Î:<"œª¨[Ö{ø-^©ÉÎÇ %«ë8BK']Ÿ¢®uï„ó%¯q²ÖÌ*ßgÐ ™ÅîŠI÷K–ÚŽ®ÝÇß„–Bt»1 ¥n´\—É7MÅú¾ÉKöoâCºUƒôô$ERz¾%a…½e‰޶¢Þ‹`æeª¦<ò |8~x1âÂ*h€Lgç%øö(êŒ4œr±¸½úIt¯DòÑG6^Í“` ûOÉÒÅsóÆ\ªÌ ù«ÿ.c…} endstream endobj 832 0 obj << /Length1 1511 /Length2 7301 /Length3 0 /Length 8312 /Filter /FlateDecode >> stream xÚvTìû6%1º[&!Í6RNé–cÀˆ ÆÈ’’’/)-ˆ*H"%%!¡tJª€4ÿé[ÿßïûÎù¾³s¶ç¾îxžë¹¯û9ã»ad*ªâ„r„k¢QˆX¨¦o"ƒ%ÄÀ`qŸãÿðÝ…£}(¤Üÿò«¡áP S‡bpaú($PÇבB¤å 2r`0P –ý;…–ªCýN@}1  ÷ð©¡¼ÑW n—¿—@˜ "++#ò;¨â G#`P$PŠq…{âv„A=€¦(Ž üò®Œ—äïï/õôC¡]E€þŒ+ÐîGûÁ€¿è  žðßÄÄ|@3W„ÏŸ°)ÊãEÃ8Àƒ#}p ¾H'8ˆÛhª­4ô‚#ÿ Öû3@ø×Õ!bÊý•ý«ù; ƒ¡<½ È@ÒèŒð€ 5õÄ0 éô+êáƒÂåCý ¨#.à÷Á¡@Mc Çï/v>04 ã#æƒðøÅô« î’5Nj(OO8ãøu>uÃÝz èw[Ý‘($öϵ3éäü‹‚“¯È‰ðö…k«ÿƒÿb.p P ËÈ‚po <æ úUÜ,Ð þÛ ùã΂õByqà!g8î€õúÁ´/<û¿ÿi  †:Â]HÀ¿Õq0ÜùO×y4"xŒþõùge‹Ó– éøoøïæ‚4ÌÔ ÍÌ…þÇ¥ªŠ bEÅe€¢âR` ".”Á-Bþ³Ê?üÿæþ5‚"þ:øßŠÚHgPöO ¸»û›†ß_šøk\ÿ¹ƒ §c8Pà_ÙÛ€¥À0Üäÿ[ü¿SþošÿUåÿ!ûÿ>¦¯‡Ço¯À/÷ÿá…z"<ÿòãTì‹ÁM„> 7Èÿµ€ÿ9Äúp'„¯ç{µ1PÜd¨ ]<þ¹D„&"îd„ÀÀ\ÿÐß=À•÷@ áF(įg( ƒÿˇ›5˜;î)ñÁuê· Ž¥ÿÜR C9ýš9q)i †pÇYR@,7œNð€ßº‚Ä( .ˆ£tF¡¿ú)-©ü‚~[R@3'ëq€òEÿHÊA¸Çí_—áåáëóo†$äƒSó?6¸¢áÿ«&‡ø£þ-q  ‚£ÿþƒÌÆ üoñá˜ÿmÿ~]àð8 0=‰‚Ý~àöâÁ›ã:vÑÕ!…1¾U‹lAQì4ºÕ÷”Š$CðY^Ä<úH%£¯“æó²†À¡ò ×vëuILsšqËYð¹}ªÉèj `j„éýð“-•únN2Q3åµà ïà»áñÛuø ½}oQÓû¿Ó ¨ï®šý=¹j¼öLZ—ü¼ê£h¢y‚Mxù8_‘ã,ÜÄQNR!ºýêñã1º‚á+.Ta@Èv¢D)ÖzA<éd"èËS3qŸV^VkNÂCº£7±ª™:ÌŸ°¥s%ã6¾eqŸ;ðlµB'—Èdä©·ž+õÞXsYü¹ÝNþj)¢[;“ùdíB¤ú~­ÔÚú9ø° ÷>Í.v’³Š®éwûùµã†ÇŒKÒqa:<7ØùÓ¹öÑgü¸g¸´X3koDƒ(¹Œ)5©ôB»Až×Ù…Šò¹o *ßtäè)ºKÎÉœÒDt쪣ØY‰Dö‡m#ìŠAëÌÌl…ØÉ¾7 Ǻ»Vޏúo´~öÞ& Ûw¿)’¶f¯öøÃe_,ì:wRé¨lhÂ"6M0?-sâ!}Û'aY¢{WæZ|†ÃN¢uÍËô.ÐA²)%y¦Ð RF#ñ}X0ÉJúªE· ª-u7õb‚­¿ö…ã[Ä-W¸Ïq[15âôA_³¤ fQê ½ß«þ£œ0#Š»»«LS)^÷ÔWn{û+¹o5ªÍQ¤»_-öÉÝT œ¾íxiÔg–0EÜ\öjÏ»·ISCÙç«îÄ=%‘dLz”¥Êjmêè+I±‘_йPÖ¼8?jp"Y™bÿ¸Td¹èž!Ã<¦ûZ‘ý|#dì>`ŠvÕìñ•`e(#¯6ßЕ÷Â##mžzQ}º´á»îCTÝÛÊsoÆgóè­çu¤]Ãöj–f\Ufêæ‡>ËÑ´ó¤ 'ýšçÀð6› ®ê¢ü΢nNpZ߯µC˜Ñ3Õ l7[±3žÂüq“$þë­~läS‡²Ózh %º-C½ÖÐ:¥B£Ol8å³ÂVšŸ]E+HünÇ+fÁWml|ýØÝ³"0¿¿ã¹×ÌêÜÌJrŽÃ$IÌâ0÷ÒLÏó„´bLŸ¤÷¨Ÿ#‚2HwJŸÓó9×`éóÒ¼ýó)2a»ÍW“~*õo(K­®*?ŽíË—Ú*}?, žôžN(̨uVµoIE¦ìÝð/³ÛL£8a˜zW:å—.@x0*)"Zïüöf¬¥„T d·¼¥”¤^ï ÷~›ÙIûGb5i½hQai€ÆÎ.÷ðsv"SJ±êÍbmv„Õ¸0+l vzÑÖ­8˯Pþ²G[猣 àlû!FÛÇ QW(!ÃJœ*hœÏ¸ÕnHŽ[ô‹ðžê† ù‡7+]â0=ÙØåÉl(Œ&’­b»}h R¹&˜cHE.òÙ®ÑÓ—]s7oªGü4¾(ýi]@¨§t'±ü];]B®¡ »É?kŸpk”Þ¢Ö¢9.Zë^y÷ò]›j¬[+Õú›ø.Ól‡;j¶«œ3áRÛ|^h·%¿‘š[úŒ‰ \ kÅËêxVÕôih$#{ŠºàÓÇ5—OÎçÔ] U´{Wá˜Õy¶i›—äÍCFPgEÊ d?îQi}± (é•’}‘Ó‚ð*‡œ‡r÷·gèºÉhímóGáØb³ ûØYç!6û¡ýÔ2é›–¢l{èå¸çCÇŠ+ÕÔ\’7Iµº•Ð¥6ÁÒ¹T{õáþe,©Ÿ»²U…Ñãª)°õÙüB‰¨·~€Ü¬… OåÀX_V=Àõ®â•ë$³n!Xo ;U¼Jþ?¾\гX•âõº"Á“ïL6’M•ð|éNðfÞQ\lgYwsÕ5eÄ&#R‘ Ëý Ó­¯f {²·Ò°>Ï6ëÙKӣ޷U€{ê«Å2w1£Ú´Ù,c­»øäq¶á‰Îݧëw¿ÖN¤UϹÉÜ…ÚCû:~r‹byvÆv˜×ÊÙEÃOGrëކY³÷¾ ÒîÞ©yC2®bI0£±Õ’þîªü§¹K¼{£w9žkW½jõÚd¿ÛÓ±fZWªIí~ ÞkmÊ3ržbbÑ ï,¾*/ jˆÒÆysÕWv=«•J·`u?Ç5=Ñ/ÀÖ“ ]Šbg]ˆ½{œù²=á¶Í­=)ßÐÝÕ{r\ÂZjar/4…¹ h#cl÷·b¬³=Y³T0ʦÃÁÛG޳ uUwßÑß!¶(4Yø|FPèåùÌÝRÚfî$³Þô©µ÷Þ]Ëü½ ±2Lë3Íþ¶ôDSàk«ÐÂ’ç™ÆÖ‘ >ÆÞÈã ®Ã(-ýãÐq…$£=õa¼•=Z3¯«÷^:ËG¬±ö°9ã?ävçñÜÒ6—+æå&NCÕù…q46Rr²–æ£@·x“ÜyÛ= ïÆ¼=ëW©Ë-a9occ…j„lìrçÇ‘n½pãîYêéµy<‰ML¿˜±^•a;ÒJmx\Æ6ë¯äEz÷ìÇY0ðYð¹¶­µÓÓõ#E/žVø’ïpŽì3Ç|LáCOSbE†·¢$Lñ§&Qܾ?´tÏB¸:Sü0ÃáШ¬ŒjB»rì¿ï¾;ùESxÀ_‚þKAÖŠ ‰%5竲“bÙRŸ Éo–qÜ/x—¨ý õ°ù0¼hÍ0ƒ<¼E7RþÜ÷ …Æñ㩘×G'âìŸÌf¡»b;Õ‘ÀíìÁUöÝ×é÷YæS^]º Ôh^yË·„òÏ9¬ð$N¸Å\ðB7%LU§žÞÌú>è3wë ™ðÐò—hÊÌ Dö«éMu™×}Lêç-'µ?xVŸÎv 4ÎôÀc`¯JdÕ‡‡6áï¦kÏ„§8e2ûíÉ[Œ’E𼋣fA¨£Tå)"y Åïvå¶Ypì52˜ìûîçØm¿¶m牮iÙ aX}iªÁÔ"UW’a˜?5²gÞ/§„ªñ¦¨§±°¡¾ìgü¶ÊUàOPÆÌl4ב?dtÅ_nìì\4ñ{&óZÃ/¢{­ÙZŠAíP±+÷$‹äñ~÷dÃq c‹«)‰Jý¶¢ø»9âHRà %jnï9êQõ¯†Ñ1‡¾î‡„’ö!\³=ù<•x¥í±§`ƒj’š{µÕ§ÓªòK Õ.[º†TÐ)´õÆÎ˜ñ4šO¬²b1=&%7’²oÈ,½úŸ§Î'ÃLaU,5“¡ƒU¾-ñ:ÏÝüÕ‡Y ²û½ºv2zWøÛÝïlÜBwßgÞV%0õÛ“FUoŽ.ß §h} qérq¾üèøíZ“o&YÓÙÒ]'”Ùkûj Þèòhà(žµÚV¸ãWªš¡äÁrßKxÉÆ—’ !ùbOâîvâ«ë!qåï[7¼„P==8ΰ•iÊZFnD]d¬µS)ÐHÇmÁB¯ó8Ô¡ô^i/¬<ÒR‹g…u/h'št 8Óâ7P@¨•–26…I¬tIØÕ¬¢øªÒ}½>ÿœ Ø?ººcȬnòÉõÞA\BÌ,íRe¥@Säë‘òìË”œž.Ñ%¾*úF‹ßõ÷zfY…™±2ÐÂA)Àê(kïeœ£Âêx4‰éU,1/z XCYy7½ä¤ïtfg,˜’0‡—åK»="ñ¥Ù»ÑH™Z†¹¿j¥'£ñõÒ/r`òâÕ-¥0jåùMÚ+O¥Ê½®9K¯.ÆÚ­v³˜;d&ìÌÁ1=ßôÚ¦-E¦ûŽPAe9d³¶Ñ—ŸÏˆ©ÔL÷‹½'ÆÚ{¯lz‡±±'Ý,â"ù³›:&{j¾7É.@ê‰ÝÏ;ÅWŸ,f¨©f6ç,¬¯QdøÂ8ŒiŠÏ&L’ÊRÖÍž@òŸ¿(î¡7"r3wânkŽ\ך,ÿÆÑÆ)÷¢»²Ä‰q›É2f¬ýæÐv°¢$À´Î!9oöA”ð:ze†}ôz)oîxæéK­¼£¹µRÏßóߊ9ùYïˆHù@QÉ;¦þˆN³2þ[-}^Oü€>å ¼pÙw Ä*D²¤ãü“jŽÖ Ù²Ë8äM^÷îjýœÏhâzZôb€àÔuZ/†&èÄ ›®×6ü׃Y¦hÂ/Œ(J22_ëYý6"?µöÅ— ³hÔ“¨…öÁUæbe“B÷ÛIÿ#±‘ŸîN“EÑLÎØ@HÇHÝÜgùAI¿r§ ®”¹ö·šÄ ÓYÛû÷vöÛ¦ ~Ç ·#±™Ûì,¡Ü·ã?§as[ƒ,wÜ]³¿Í*€Õ)QŽX<Þ›>vBöI'õ ‡®³6_˜öx™=oZ»„“Ü&©oâiPÑ’VUjâêîÑ]Áín0Ü,#^µ6h1ïù™´uƒgžÒøc+µZ]f¾v;àuèŠý'908Ÿ(~‰WBì ÍkŽÝ™}²Hò 5Jit¼Æ¬Ë r¦õ%f'+;ËzUxÞJ•¢1êeq!øJ“-¶®åT¼Aõ0Œ‹MEg‘O’L~v$´Âcl’Þ^|`'ݢѭªÅIß°«k/~ÕtÖ^ÉÞÉÝÕ:O>¬Pì‰_%›ûáÜç£4O±šÑ°â4&Vîˆ$°Í=l`5w-}²ØŠ´üæ7Ûžfè;'ü>-Ü‘v©›7/ûJ/ü-}B­CµC³h"„"Lø9áÛïY¹{,µnÝ#fï|ÿa±Iø¹û~ä»V‡N¤³ëöjÛ–ÊãïÎΊP)u5ÞJé×K.)mMB’{ "!úlŽe^ýöê²KÏ%'^’ú´ ^:p|mÒC ý|^K)À¾ë/k³ùØÆ2Y¥·=÷¾d®ÃÛg;™Ái~ÑË‘3âvÁdòü‹¨§Vi"1Ífwµ5ÐdJGÊ)wž§Õõ<î”-Ò;¢6óu×"ž_„û|Ç|¾AÏðF°²M+á{’h¸šý¶b=¯åá-˜ê÷WüÎXŠÒdñõÖïÑd&õÉÈ‚²“ÖȉjåÚæcfû‘¼„O9ëë¢Ôc¤%‡înkÃ[Ÿ=‘îÜØ?I•»ÄBŸ.;>L>Ô¨’ýËóV3ÓÓj¶r=4Ø@Ý«&ËŒÃLÚšïÛÙÈ2Íy7Æ­ê{DAÞŒ #P(¦næ(•5á¼—û¾X¢k´Û”œž¬ÚIÅÓ;fWŸ|QÂqO•M™·Jß©i›÷–À–OÚC£~ X™ÕÕ¾œxƨÁÍïÞ´DƒŸ%³Sx‹w­üê;ßßi"~Íl Œ`ÕB“ +%WWJ÷­(.ù`÷o¾¬­T¦´ ¢¥X9{Á³@w现:_‚Ÿu¨…a¢Ò]R‰n Brͨ±ð<Ù|’BÀ=n î–F´çSx^lÖVövjüRB‹M&yÝ%ïžú¬7[&Dƺ·žsÙïïÎd„9ƒ] ŸÃäk¯n1EQFN½ÈÆؼ1š?ÙV~mWÓÑ›ƒ|x`Å‹GS§Ö¦é¸÷ÃCß?(QŒ«y`©h_{ö^Ý­WÎ~Õ¢ÓC |3ù¥†ácªfw1ß©œµbîðÒ 1Ì÷½ðôjÓa•ˆ®è³Šº€ûP|)è$j25¶ÒkV5²¿qÇ‚H•óÐa¿#”¶"iû^À‡YÂdA ×2 Õ¯AþJ17ˆ5 ŸnªgÕwdÀËî]›òc_ÿyÉeG‘kžB!U^5Q©ØçƒB°XegƒÂª"1N'îîÆH:–Чhò¥UÚ)6t³¤k‚©h—9C ³}@Á•ÃMªùÕöì^²¼ù\…y©ü¾×ê¹n×èl™€»C]Øéó—ž¡„urÇË‘àîkóؤôÅA iÑzêq%æðýéHÛDŠ üî†7ãc!?^j‹™ê?¶1L…?ßcö$G¥×³­ìlð|ÿ8kR˜~ÿ´ÒKìÞÊ®ùs·Pj%•€¡íäļïéç8žÝ·P^écKG‰höèö•(¿VýsIÀ|‰€ÖYÚ±Ṵ̀GøœÈ‹ÜÎíÎqG ûÃû‡É$6&I†eöõŠ·ïÞ=þîÏC))ƒ’Z¡qƒ±X >¯ø‚`DxÐÖXO=ô¼¾t8º%´q³du3ããùüæ¥)„QcÜݸb`Æ»m} hc?}e¸+8Î,`™snìXaE•?î3«ÿ¥t±³ñxE’ÐÌ@J‰¾ècQZsî|ûòKvøG…Öö‰VÉz/C–3kWi%Χ¦¬¦d6 Iu“í’Às«ÒÄ‘%¥EFÝ™§¤œ÷třҕ¨³«/·.×ëüz-SËœ±†o%?DESžùë[Â8ÏN¸{õŠ’b‘HK¡@I;ü†íîw`BÕÓ¶y¢«d¿½ËxjÒ S?&F–]ôûÅ:.â®›ê`ÿ1ÂŽ;½¥Þ³êQííë¼E~ IËÍF%æØ=‘¹Ñ·á±úÜ¢×]%¹ úeaQÓ³ìDó¦óڹ܅rí¬7ûa6ªoZiú]é¸_ʤûyÿ7¨¡¤[Õ¼wâ´Ü¼z)MuhVÍLHÇ,½Ð^—³ý°uçÍ8©+´å ­úhDÑ‘7|®8Îù°¶vU~qÚ‡Þµëš;§ø¹ºHò„Iµ5T;á ó!:j$ûg9€ñðçQÿ†wÝ)Ñ jÏj’|0%TÔYø#7ãln&»Ewà ETp8E&¯C冤dAÉ–PQSâ5;Ó%Ôai&ÈKÎÛª3H®™‰W¦¬_«÷å{š­“\‘Ö’ih[sc1òˆôgñ÷}÷£„¼d“#ÕÂ;mH¸‰µ˜c‰†ºGBeÍ?’Odß´ð¦x[‘Jø‡§×hUùÔEYƒ @H&øa{£¾“òpñÄm›oû‘gKˆŸi@¢ëøo¤:sÜ?Úºìp18VéP॑…U›_µ †+[wCÏÖHç\Sx\oÄ^ô"¿LV‘í1Öã3ž´1ÉÛŒ=ãUï-Œ÷SFéL1q†±ÐŒi:®aFg¯Sø—§øT3é¨õNÔ)]ûˆU褶7îµIrEš‘öôÎÐÜz˜0ÇEÙ0/\ÞvÄ0GS“²ÝèLÏ´o·•4ÿé›ñ½ŒÎÀg÷R­›Ð3•ñ™¢ª6­?5úMµÅOœe;ÔØQÓS ÜßyÍ÷z±ãm’!2û³0s}ßX\þCîøgÑ{ o²Ÿ§à¿À3½ãýiŸÒ÷Ã{ÿ-ϳ0óÄ@"þƒNbjÎrë¯CIÛÇôôãq2Ɖ³Èòò/>wømy…;ß–U³yŸ3ó]7é‘ÜÌþþ5—zeb¾±îĶ«¼µ–ÍëUÚS5VªKÏN>ꜣ)n –¶¨âvó{Еg¾6×™•ðå¶æ”ŸEEqõ^ŒÚŠæ7G?¹LÄß4Ü2DÞ̵ÜjieTvÚˆMpÐB™ñõñewÞp§á…³4˜oˆàMnxc¿ñžÑþÌè”ùoš¤æ$#;¨ÄR|XçîÄz)ÙE]ìÜPnh‰*±¨—HþPòV§º‘LÖñõ‘Apú£³»Ô)Ë"¶ú‘id‰†å7ùI¥7w2¡×…À©J$(ÖÌÏ—æác…[sû[7oF\unö…¤‡‡±½øÞ(öèñcº¡’Ay²¾Ò²ƒ cq¬,ùµÇýf'¯K·3Fí.¿DÍžÑlcçJ8ÃÀ¡j³(f”?g­¶t¹£¹S@ öBœN0Lt6¥xƒ°*Tûnf8czCŽz{g%¼ŒÈÿ)›H”|LIƒ8$rÕøŒhpå‘¥˜Ýç®òµˆ‡1Ó÷ºE7j>¾¼¡)ÅUåõlBÔìëDzŒª’1»( [¹ʪ0 ©Î"l©jJ$VŠT> stream xÚŒ÷Pœ[Ó ãîî îîîîîÎàî®ÁÝ‚»;ÜÝ5Ü-H ¸_Îy%çýþ¿êÞšª™gu÷^»WïîýÔP(«1ˆ˜;š%ÜX™yb ªÜff6FffV8 uk7;࿬pš@WkGÞøÅ\€&n6q·0G€¬»€… ÀÂÉËÂÅËÌ `efæùO £ /@ÜÄÃÚ ÀutºÂQˆ9:y»X[Z¹}ìòŸGµ €…‡‡‹þïå{ ‹µ™‰@ÁÄÍ hÿ±£™‰@ÍÑÌèæý?ÔüVnnN¼LLžžžŒ&ö®ŒŽ.–‚4ôOk7+€*Ðèâ4ü% hbü[#@ÝÊÚõ_f5G 7O àÃ`gmtpýXàî`t|ì P“‘(9þ,ÿ¯zÀ¿K`adù/Ý¿WÿEdíð÷b33G{'okK€…µ $)ÏèæåF0q0ÿ+ÐÄÎÕñc½‰‡‰µ‰éGÀ߉›$ET&úþ­ÎÕÌÅÚÉÍ•ÑÕÚî/…LÑ|YÂÁ\ÌÑÞèàæ ÷W~âÖ.@³ª{3ý}¬¶Žž¾ÿz¶°v0·øK‚¹»“†ƒµ³;PFüß&¸?6K €ƒ™™™‹‡t½Ì¬˜þ"W÷vþíüÛü‘¿¿¯“£ÀâCÐßÚøñçëj⸹¸ý}ÿéø_ÇÂ0·6s˜-­àþ°˜ÿÂ'ïbíÐcþh<ó_Ÿÿ>|ô–¹£ƒ÷Ÿð¿—IW[JTBšîoÁÿu‰Š:z|Ø8 ¬Ìf.f×ǃÿÿ²üWÿ´ÿmU6±þwnÌe,<ÿ’ðQ»ÿÈðøwOPÿ{\hÿ»ƒ¢ãGÔÚ^Ÿ™ƒÙìã‹åÿsóÿ½äÿ_ÏÿÅòÿÒöÿ7Iw;»¿½Ô¹ÿ¼&öÖvÞÿöt±»ÛÇD(8~Ì…Ãÿ Õþkˆ€æÖîöÿ×+ãfò1"–vÿ-¢µ«¤µÐ\ÙÚÍÌê_ ôŸ3ø ·³v*;ºZÿuÍX˜™ÿïcÖÌl?®דúÛü¥ÿÝRÂÁÌÑü¯™cåà˜¸¸˜xÃ}üâø²| §9Ðëï¾01:8º},|ÈóX8ºÀýužœ&‘¿LÿBÜ&ñ?ˆÀ$ñ_ôÑJL’+€Iúb0ÉüAì&Ù?èc¹?ˆÀ$ÿ_ÄýÁ©ü}°¨ýA,êЋÆôÁ¢ùq˜´þ  ÚÿE<>“?èÃgú}è3û/bÿØïã ³ÿý×y0™ÿ²˜€ÿ…åfúW3ü ø(ŠÅø²þÏöôþ#üÃbùø‘€ÕŸt>[y;Y}\Ç">lÖÿ€Øü~HµýüÐj÷ø!Öþdùö‡™ãc©ÃG¿ýÃÿ¡ÕñO2‹ÿÇý¡ÍéûƒÌéã½â`´øSv–[]þ§JìY;}Œ½ãŸÊ²}Ð;»;~LÝÿÖ“å£".ÿ€ò]ÿäüátý¸6ÿ¸?ˆÿ,þ¸h˜Ü¬\€ÿLúC¥û?àG<þ?’ðüÇá}hú9ë÷?à‡~Ÿ?’>˜|€.ÿª×ÿŒ§™»ËGÜþ¾>?f÷?øï÷#è4ƒ[Yr4ãûdÓø©ó¡Aß“á`Z`â@+ƒ†ÁwÅ¥Ëý :¦>'dËåN$m¬e}O‚úVx•øÕ÷´­:¢=E¥ãÙïÅ(Iuî îÇ,ÖðLÉ©HÓ!,ƒºð¡ß«³Ÿf°-xh,E³;7’rúƒç ”WÓPÕÚdøÒÊa=§üKÕ5ꬮ½¸ä¸º8„à·h“s”¾¢ÇŸe±—}+J·\&Ó¿cuMíØ§²ØSû(ª>¸œü6¤¤˜á¥ÆÅalj‰Ýj—N¶/'I†bϽ\—Ýò’ùÍÕfêJ¯”lý®dÇÕˆd4xm9×”ÑåÊÉw˜Ö¯œ”›ÞÜZëï†æÕLß+ã!Í6¨’w6^mõîY`ý< êq&æQ®ô®‹Ÿ4,ï$µW’2“òØsê»|&þï‘©8µ*WÓMüŽâå€Àt|(?åp§4,E3%ÌÖºZ‘©òÛÛ/¢ šÃ{¤4êVIe3†b¨È^`Ÿq¨U÷¼Óè{]i褷bøöìAúi±…Ž¥sºH#&)ã:ø¸©L¯Wa¤ ÐãtÒzSLGÌ· ­ÏÈk[/Ûo­ñLP€w©®-ƒ›;¡’4v¼þDïõlûÚpIˆ„ àRŠ—ÝËCØôóe]LƳQ÷¤Ùgà²(‰J¬lÜ«‰ÖP€X©³ý. ®ýÅ ²É߬ËSxI«Åþꤷ£aÄÊákXJ/L B¬­&4n+¸O˜+¾–&Í[òA#ß=© ”ÚnäqÌ,”w¿üôHâù"9‘íó„IRõ€ú è÷©”δ`zZÑýãùçOMØê`9ÄÝdöÖÁpîň~…ÚÞ°Øð=~0û-ˆ¸ ¾É£ÏIÉȵþJæ,ºjÓGDöÊ¡Sì ‹í4„þ QÙÊecÇ–¬³v,–q“»’·Ó'YH¿6‹œÓ5AZüÇú~+ç×CÅ$à°–UÒ©œúÎަ¦ÛMD~v·É‘ü‹ t;  úX7Œ r5mæ¼ ¹„A#L¼oÎ^Œmºù¬òÌÙ#ndwqÛnº&Ê ê ~ Ô«Sž·86ôŒ‡—¯Sš™<DÑ=‹gçq÷Æ<Þ fl«ä‰‚¢%µhô. Bh‘â¬]ˆ¯SX}²ø\Tq«Fª[û6AÜù§#"¸¢rÝŠZg¿šöš8¤žíé]l‚åˆÞ…[NßÀ5ú C\¡¤Ëñ±9 ÖèÖ¼‰+®û»(² ¯s ã.ûöø®[c›R³1ÛfrwÞV(Õ*Œ•°hk‰#v”Žï…Ó(ùüg»ß¾3êP~ÉX 'HtÜÄçq,A|œèèNj?€«ç¶éöÁ•YX;K§pìXx©ŽÏRràÆÿ­jIö™O¼óó~Þ, kµ,]èĵßÊ\ŒTNJùñ÷óœSŒm[žÕÆ¥PŒk wêkÓ(=ƒ)›gVâ˜îòÏ5êù©Ï÷â6‚ÖÒ·©…J< ïWu§§^·åçÖø¨+£—4VöŠ#Îy׊äˆ#,¨E¥lÙ¤õr,ùf“þ¶Èµ“ y¢'Gj…>ò„“]dA¤Ž‹{‰“¹ÞÅĹm$‰êÙ¾Çï öX#¯0´Îc#"r<(M½_ÏP)Òº¯y÷rõÏ.úž·…ÉîFY’ˆ†ðíàÅû IÇi‹¹£ábá] Ëk-=Mª‚»Ñ*à`ÓÈnÂ7#ƒümb.Í/8Û>Ňû)âsaÔèw@ÿúŸ¼803 BAaÝ·–X¨×}«Ç„¦w̤a³ ÎêJ òPúAÝp"“Ùs5Póƒ S)· ñiaŽÕÄù^òíÝ1QóîcD¡Fss«Gˆ <³ŒcU -DYø1#LŽ Ãy2äøzEë:ôÒáÑh¥ÝC2«‚¬Y+4§/í•uØ=¥ÍC>1^±œ=eö)aXÐÚw’šÑ©wbJ^²áOp6’öeŸ¬hpµÇºÀ ¾ÏFÄp !ŒY=ùì»ç=€fVL{ÀW1Z5=رӬyó»ŸF.œc@-"°9±ØåùÚ­ùbzSØ‹Æ ¦þ¼fÞhƒÃNr¢ÙÙž±l¼u‰ÖõXÔ¥j–͇C1Ãé‚mœk I•@=z¼¯Ù5£œ\ ¯D6èq¸ÈGø;è_zØÛˆ-T›* ¢ñZæíœ÷ DÜÁj*bXO¥¬V!Õ’ùÍyÛß3°O1ÐO\åÀ[„IÞyi=!ÅuUw}srmÕ&‰ãtfHø¤€LuþZ8”°ºEÊ22LÝîê5öUF­8"{0çMóÔð܆ë€-GbÜC*3“¢HÝðBÈV(öjìWÖB2㟹/Í÷'Q+l:öšãw XxÚÆêc°Þ'û”R>~B ×/$ p¥»cÜÚÙStN”ìw6™˜û¸ßî” ;Y¾”ª;yĉ‡¦'b BÇf­!Þx‘g|=§³°»Ù÷JNÂ-<äê«ØÅeQãÄ¿tÁ|RÀð°oo1¼#¦Oig†‰•mN¬£ÿìƒeÅ „n7r}çp¯1|¢ÚÛ‚}µ:c=C÷=Ý–C"4tR£cÃt=.¤¬¨H¸[PxõSۓ€‚ŠÂS›º8ë8㺃LWKZެ ‚à”8q¤Õò~Q\QÁ4í<ÿþ]'í*ø—Š-µæl¿Ñ} Z1ÓèÄ=·IŠæã(•㪩k#.áTT]ÁÊn¦R³vÚYtJ‘>}vB>Åßf(bö÷óÂŽÛšý^ùú¾MFøî\P¹gB¬Rç}µLpZ*Õ'<¤ Þî17IP#ÿ`%Mœ Ü ”×,É$«ÝxB>ZÝüޏO›}Ñ(RޱÀ{8‰øeqzò3ÀÌuÆâãÏsä£ÂÝEîÈB …‘ âYç%.¨—œ‰jÁc¢0¦·Çªn²Î;C9TÛÞueIW´»žÚ8L,~ÒÝýžufä&›[é<’Ù-{“W˜jë>*êÝHFWÕPÉ"}&orj:.H=ˆÊ̺ ½=†×2%n0 Q‰C]¶±p€N˜p² F9p«Íä›ÖO\½ãæýIïÙØ(ð .‹,ʪ§U'Þî+>ĵÞAÈÓw‡O%´™w?{ðLÆr3Ãb“Î;ç@w )UD¿<4CŸ†y€hçúÆÖ¹")ó®.½ Mfœ r—å‘ÓvZy @±Àhrè *žUë­ úè@Ò¥ænëíAÊñeMÜn©|ŸŠoì~k䓊"åREûhïBK»*Ž›-åBçŠlA»ý4âµÞ^½”Q+¿iÂtŽý­I8Ùo£qmD£·ß—à˜k‘¾ïå[þÞÇí3‚#ðtØéñ=éTit/¯l“²L‘‘þk-øØ€tä8¤™ûÞrÔÉÎK3¡¿§^¢C íÊßÓTкýy@±MhN!áñ„ªaÜèC–:%„½˜¾‡ÓáCÇ·úL£%\DÔwFwÅ ìþöº97á—ãR÷¬¢Cc­E¬ÑŽq‘÷ k‡âAçšÞ„:©É_%\3ô5ö`{å?[9yÓ^*¸¤ÃñDÒ¿ãtçnj}÷fë â„4&‹é”ïÔS6í¦óá-,óødÞº¶úÒ„ŠH3×D–ĽgäÏá$6è‡ØÍÊ–úüNàðü“"‘ žŽ0¾MyašÊ]°¾\€uF?\jÝChˆhrÕy©1É.$d'-˜8@UYËl²7Gš„Á$‘³d(1ÍýÚÓè>.4SÃð±vÅ ê\5Àª-êmÖá þeÜèO¡ˆ5AíY€ç9&H”¬äM6¡å„ᬀhÈ%tô|×ĆÜÁµ@Í.ºäg¤§ë`îýˆ ÛõÊ+’Ñœüñs/€—îoÿP´‘œæ“<³Ïe§$K6UqBþ”(¦Ú%­ÎËÖ1lØàè^Iö¯Ó ϺœßË$n¸ŠšÄèxå’F¥|ÙyÜ4‡P´¬b‘šn?¤¸O™Z®Hýz¶6³¹?´Êâ½Û„½yU9ìÙ%fy~XUó%oÒ™E²OÅ¢€b{¨#&G?í×OáþÎì#b°Õê¡H‚o†±Y„³M¯­_¨,d}¢&÷ ‰à³›©ÒšaÀ.[UͬS á&Ÿ:±FB‹.tЖÂu[ o^u Bæ,ÃÌ`5x˜öü o4gºÔа6(ñȲk°ÂX2Ÿ}Ч¥–¥v¼FŽ˜À¢H¿•ÕKÞß:BV4ñÓÓ&ÅÕcÿ¸C^![Ö¹r\æÝ2¡L´ÛÀ ­*u?ǹ•ë2®j˜pï‡\€3Ýå¸?yšH¸ÅåuÈìH‚üC®«áw^óÚ@c_Âl~D„çDb•SÑU­ã‰¬0*øâ¬ J‡Ô˜Õ' ÏÜ y=Q_Z÷âD{·b>*N¶ºï¦ý@¼#R¿¸…I¨mç4hff¼•7BÅ^ê$[$îOŸ/}~Ös]² ¼g·•í¸fªSSªšqБÕ'µÅ;¸ðñe)l‚ÄKýú™s@ )û"w±’ìAÝ]äÐí)†¾Ô e£³1êî’ªAÝd¬×‰¯}1Õ»l“=ä.Oùä¢%¥$ šžÎ­A{ˆ£$¿ò•z¼(K2¶ëBɨ¢ å£ôóW@Âi‡~èÈÓ¿ËCRSƒ‘(F’w¼´=f|œSÌã6E™WËŠå¹OÜ6¾j›‰ÁJÿ–f–“¸aÝ•?â€p Ú ÚÝuAJH{ûVîƒA­H7=ð\ži|‘E ÕQ5oóYP,:…Vl,«bK-7ÃÔíÙ%ÂÌ,]˹ûÞ-HHOÆš˜ßÙ|g¡XÇóâ%«¹y“e8”N¸j?ÔØ¿lÞÎv° ölA.q–îŵݕŽúT¢6m”….\!å< â€Ê±:a’ÑwX5‘vžB¼—~º©[ãç>ÚŠòp_~™ Tª$ïdÓF¢¬ží/_ãP­‰—åöD|NÊ™l¬ ·7RI,eî_~Étà>ŠÁÝkt¢Q X¨÷ž7Ð÷‚Ï;o±œ„[Õ"«Y2²1T ¾ "väV|¿ìÉjUZ‰8ˆÍÍ™ñÜÙ誈—ÄÌ‚«nuæbýXzD ø‘¿í ªG5´ÏùwÇlwþ¼ö¥½IÌÿF­d8Æq‚ÈWÖ˹5¼8(3‘›iÏ0ì%| ¶°6žà:¯×à Ò«H ¶bú9ƒ®Øú0°#»ˆn,ö¡zÕÕÝ;7?¶î2öÂÆ®#5Uü«À˜xŒÔJÛ:-K4›Ð.Oå˜ Çüe} ¿š÷W}S1=ð3kåîaÝ^eNŸøµ‚yé£àc똭®æ¯:¿Dõ»AܲéѵØ•q‚z!#€»lÙžØï²VNûKãßnsÀ„'tý|’o= ÷o7°*¡ï˜¸Jv5‘‘ƒ¦%2J£õè³4?l6¶Ì"\xv¿P¸|™–>ÁϤ¥@;ä¬+ó/ ôÙÕÞĪß²ÆÉyFx,>ŠðÉlί|û4€”ªð_\ƒ ]93™—ÿ *ZôNµÅÊ>FúK’¬dS.§Vþ]‚Vôľ’`ݾhÃŒ~¬ÁŠ>ŸŸÌ¢Ã‹âŽhKžƒ½ Íûù¤G&Ž,>ýZ͵5>ŒnúÆ¦Š¢kxtgéyùxÀÅù _¶!7¸'±1¤¹/xiü÷ú^ú,½.Øx UÍ/í–Ê“„KïnI—2ˆQÔCŽ'”Ý7`ªžJ"Ûnÿ®lkãQ”Ó²?ÚA ™Òÿ|RR>›Ã…Å_û8·CˆoFz¤~‹PY‰V‚Âha "XÅ; LÇÒz9î¿|Ë75­¯–a''!\3N 5T¢Bº½¿y}N¡)~]Ußž>Øæ}NÉÇŒUncÌXIÜ’ö“ú‘§q}÷Å–¤<•™/!á3“è`̵ ™³ã®y¼A®’`/”€Mõ{õ7s‡2K-;?‡ ùï°W{’ ÒóÙúvTøïHóŸ’'0Úv®~M$º?ïqjTˆ^/¤êD»Zúå&£r_”Ÿc³€7/yA ÁI§šBVŽªÞŸ„62= [uß„©š/èzí½38ö…‰xòæ1‡.O`œ;4Œ½§àX·a ßp)…§šÝøBc ÞÀ§à/VoOûztèªä†×²ƒ¢%†ÜÂ|™Z|Tmƒ |èóìxØú)›á ãª1âÞ½Ÿ)[kôá #š=èŠ=´¢·Ÿº‹±>ËÔ AäßàY†f&» -MnémˆúªõëáobÔijÄY?[çÞÇOØ ‚ýæ!PzªcïåXYjÛÕt~¬ÑÉð%çéuÜZóÎã-†á¬Wú|ƒ¹2Ÿ[Ûæa¶H·ž|"y½\¿çIêf5õ˜^w̾åüÝ`¶¥<‰ñ„óΊ_dî“tïTâtrB`/ê4åØÅb bë‚T¡éŽÁûÄ|?¢)ÈlÆœÞì¥ú·™úf”Ÿ¾> g]÷¡ð˸¬øŽ0˜r2$Oñio¸}vÞfCÅjŠ*¶˜TËÀý[;ÙcÍ{„+o,}ïyå¢lND)/§7ί‡ç¯eQÀdrQVP £ ò€¯IrƒÑÛ­™Å®6ß[Ì\á5µ‘~ݰË¥ùr\• ŠL”í¤ý¶BìÍšÕÚ=˜\ËȤ>¶_c׉‰­ó`½cöœØôxO>×p·{q³·÷`eë:èWœÞ7@”4¿r›Ö÷~D}…Œ¡r눻"ÇÃOÒæcjžöLw7$Êk¦7;~Õa}Ùí‡ð„¨j»ÕÀƂҤz¼"7,Bgß‚HÛÚ U˜¥5X¦¿u½‚~ªêe×ÉVQBýê+žÄÐ=®1—Èh¡ÃßG  N‰þº^@ëôEMæùämù>U’LÊÙèõ MÜlàS¢H.͉ŸDïAJ~UPŽ«™W¬O¡ÃÈ*þ¯o `ƒÒ®{J"íî ­‰nl÷eF—¾PC,;AºHn(ÛjðèReo9ø£Ì”·Ïøé9S›qß«m€(dïàÏ4³)a"ÖúÐØq™DW¯»hIŽI6µ= Uºšo~D&¨«ÛGKþ‹ìˆD•Ħ¥åZ(®äõ%å©f)oß½‡mºÁП0˜¶!Ãv@XÞYÇw,Á¬Ø;Aæo1 Œ±·ìS9ŸÇF†Üè›é,ÍÅF~Æï&ü‡ƒóWîWá5–½7g9X“Z ¼kê»{?ˆ¹P;àï#¸eäÛ+u!sŽˆ[vÁûæ¸äkÇòf¦÷º(­ï¥T׸ä: nÅfއª ZâIíPb¡ùñi’¡±ßI"“pëyßmÙ3ô£Òá;ÛïÊŒ,뙞Bbf‚x¶;~]ZßUÇ)øiËo¹GÆÍ£:|½æMû€VëÐ1CUZª†E¶•]²!rà¹W þÔñˆ¯a"6Òö•ÊÖ}€‚[ýÍe$šë½~ž›"rhëf¦;}ãɨ•0‰”¬s€Òb¤›´‰ôÊ[ÙFC6‡‡@Sˆ/ÿÐZ$"0wü–ÌÚo&d·îôlôÃf f4¸zäR÷“&CvÉWºxC< #M4¢V5êÀ*¼½øoãþîÓ¾S;Ž–®”u>ÊÑ¿_%ÊÊÒ ~óc㔣T íM×,Þ•ƒ”¤²Yéf7oÛ…2^Ò¼sh{ }5¦5ö&|²F˜±´ÝB{¸>+£@…ôuºD›åFç}BÓõ3x€òB8B½ñ¹hÁ# _fd £˜pXÏÌŠ3Ã.ˆâ>Ꭹ™4E$¹6aZ ýqîÄœi+ÒÁ4–+N $;—V´yǯ‚•Ìà0=â¤obTM_J°Mê­b3(6ŽG8äã,ìÏ&h ΋4¿ÈÔûµ¢6÷-Sg‰¥+àÍ÷ÿ–ëÙy¯³òÉŽU%ûTa±®~¾HáÞdå7 Ý<“0ô*é¸ðúðkÊlT¹·¦ Æ­Z}ûÙÔ‡¢L*,0½~ï(Óä‡<.ºŒ8ÕdÚÜüÔàÀàN32Ž»¶økn¼omcqÕW#%Ñ3 ¢îU~ ÄY+ho*õ8çOC®Æ0x.œ¨ú(_§†’¡TéjkZ;_4#"’‡+9¿ÞÇʈ4¨V âØBˆ9{4NU´¶ûÓ¢!àôcĈAf>´c©aOŠë-îà¶eP^÷‰}|ï ŽOQfn°ë4"]|y«Œé­ `üJ[Ÿ`0aõ³ÆÙKÍÁ~eyãí“Ovù=+g@Nİä=œ›Yû›QmZì‚´ÄücÀbÛ û„§&B›Â|.¸ðDßd³éÏA]g\ ¼ß; ?êUL>ñ’æÌXì“×Z¼/Ó¦g¼³Üª¾÷V_a ‹©&Ò.MÂ=+A)êB03OöÇrØ­(îöR/µ¨®e`qÚœaìâ™nÛ~n‹Š0Ãp¾~R×ñc>.\2k Lâš ä®Ìßµ~Ãâ†_¡Ä?Q§ý‚ò Ï×è¨ð:è$ý Ö”"ß^¬+³£>F"ÔÊÓœVøÇ=š=ɾ^m2¢MŽßBÓ)ááC€pƒ*â²Î'æ£Tp}*5á¤3RcŽã sÐ/ ½¯ñ¤4# iÍïéÏÙ~A~—“êö$§P'ÞÜxyØÔýÑ_á8 xÖÂm]½ŠF±°T?w™,ï©•1u럜,p‚uÝ`Ý~­jÊ`ž¢^Ÿo(+»xè/Ikð‘iu+†00> ௠XïQp,ˆs‰öa;‹&°J…šU‡:œö…5ÝáhkO\ïná-£Z<† Ñ01¢¥p¡ øÇÉqŸ§p¤8ôû4fÚ~¦ÕJ䜓’×ÝéEÓgoÈ/YÒ¬ ê¢X‚ps[²©œ±¶Ân­<¡æLKe¼F`6m"§É$²´*6²c&)ªumECöi6 íóßÅ'ˆkä$ïîÇ2¤ìéaÑ%&0¸6u GÉLðöƒ?†´Avù[.ùü:I¾&³ƒÑ+=Â’~!ÌïÃ#˜Ûºt¡ƒŽ„¯%tf˜âÊç#ÕÌY½­›*P§‘žæ«ÁÏû¼Í5Á®d$˜š5ãJÆG?Èt±F¨üP€O˜L[»x…*ÒùËB¬þ÷a»¬¹ùUûmês‡ë2Ž?ˆÓ5*SʆDŽ€+iJëÅÊ^€ž/4C_¯½}3kÝ&¹m9yrD‰ˆÍ{«kËl¨ƒ]Ì¡©zË3—ÈBÊRîL»ši]yVBFåå§ÀjÜ¢VïËÁôÆšÕPú%4D¹¤*Þ„ o6jñpëäâfõfÙ¹wH±é&³oÃ-åSkv±3Å C0ScúuI˜×›XãLRâtÆŸ‡Yiý+ØnIo„[m<ÂGXö Öºæ3ë0§Vd<Ý›ØO’`î}~“Œ_õ“–jµ›GtrCUH¨LôÝÀQó¨M)Š@L)Ÿù>7VÑÊð]‹LFÁTWP\kÖ²0›ª1&eGòOˆâ0îÄdfä"TLˆ€î'ô›ß ÀÚõLѦŸúSÍÂvñÃsz¦Ùê— J@Vá$üžB,&@õÑù~`îìÓëh;Ú2&ÿÊç{Ê EÜ! ¹ùÂ/WÚ´¯j×÷¥ÒYC(Å@Hé¹¢O…ÇÕý"F]1,"¬Žç>(4dtÞïÓéÍ §Íõ´‹ ò‘S1ç•zW¯ÑÄ *Ûì öÄ•}Q^ØÍ‹Ä=ù§¼×GaÅ"çlƒÅ}‡:aé9–¢^Ø F½Oóà#ïZó>Òo….bÕž,N”Ÿ3~ŠG©Ã´Y‚…ÈâC**>üpKßbFé›iÙdtÿY—«¹T’´ ׃J ŠJ1'q‡VžÙfwík¡¹Ë‡_Ä–Loy˜,4®¦mÍä£ç|°,6Ù`N o§•A5ðl‘ÂÆý+1JFDØ[–ôö̯ò<5`qrDÝ»qZ㊩.®}•Ö7 IÉ1î…LÌ0ÅéF«F]ç×SŽÒžÇ\ôÖ%ðôY«pî§d†¢H ®:fj&&/¨leÓarèç·ôÀà|K†¨Ç&pà—Å«&ŦÁÅt¢×ŒÐ_á̆ڭÄaƒ®=W­Nï÷ŸÇ¬Ë´ÎÓ¨¾»C@7eù™W¿ô¦ˆŒ²’2ƬÒC¤ùûí%ÎÝeiâêˆ~}«NÛ*ãìËðFŠq(M\—‡8p„7Ȉ³—RòmÚè>6QÛWÒhƒúMùÔøÍ­÷iG»Ó»èʰQKwvÈ©8•cðĚ̒•ˆµôôRïÆF÷‡"¸Ò‘Âбž¨„ÔÒ@©¹M[éŠÒKÑÌ”•Ä o†X±êrÉ¡S-°Tv:þÊ@D”ä&cƃddÏÕ^LaÁåõ•J+85 }£41¼Ûz3"³±Ü¡‘¤€¦DÞ‹mºî»†»„À¸í–åÀ ÅZ¬ð)tè9œ>às+ŠHñ¯~ø5îÍLî00GdªF£¢Õ_R*kB™fœ·›>bfjÞÎr}‚\ã,â= ïÚø9¤>–üŸ^d®î¬‰QP¾Ø‹“]ñÐ/ d*—8aõ7lø/Åx¼#„ã8èÔÊ ï¤ ÚzÔO¹vá¶?‘èÇÜ’>~ºLÖ~$¸É9fSÑß–°CQŸc…&Iz-WL§qo+ €—(£ïèsAšýdðï›ñ(/‰UöwM¥Î"ÐK›BóïÅÈ/µú6@ÏÆ˜`²K‘®bG™ìdc'¡f'³Î°Ì欃±v]1ØôKÞ8S#°åE Þ`%DÍŸfÝÉÇ©±˜#}êÖ¥ƒó¨OŸŒž"k'»]xøä÷×MÞ4Öàs¼ÐEž9ÍT.×”[¾f¤C£‰E ¯Miv1Í©üÒæ¯C7wQiÚÜÁ®n„šŽÂÁu}ðÚ¯+¾–m\ m8¶ì#Zí…jJµÝÒ¿2&¢v‘MâÓùî)oÏÑ{Ýa3F E·ßB|<.Û›„O«zðÅ‚¯xùh v¿G¿)_jº¡XÒp¦ú@=È¡-Oð½ÿn½Ò§ËøÙµ¦inUª4ÿ•ŒÉžÌ½¿¤Y}ìz„—! >•ZáШ‰$U‡|‚7+—„ DWcûìs·xwÁÁIH˜}гÐ}„ !¨¦}”Iÿ¼X¦…qÀcý/¡€¯2·'äq>»ƒÚÔý‡Âº¨{[sScómçUº}MMÛÏåÉ)?–5S„î]ÚpÜÓUNë=ìªqºÒ|„ÄÑÞ.KënEŠõËŽÁu‘µa@ê)¢BŒä*ã9šë¾µ01K- …ØB¹UšÄˆæ‡‚è ¨_fG†eL’—i¤uYƒî¸íÙ4ÄÑà“/1I±¸Zwâ›ehe-uk•²ìÞ¦-Hô^î3Þ»úZ‡Žš4Á‘¡(²Á'a®›Â½&Ù§aéba¯‹¼3&‚ZôHû‹ò&pÕ¯IèÊQ€Nççåë¢ìþ`]N$üJ|(ØòÄG0,hÝ{òI^“à(ðÇÉ bDìín¿éE>Ôí7`Ñ…ö€QE9Ë|!ƒÂƒó0ÿ.0ødaÍ虫F”܇”$ùRã÷ãç7 ÿ3þÚ|lAßzæx^2r'þ‡ø¾ê¾ÚÆÖ8öÝr·±GØÈçæ‹KâØöŽkØ‚Mû¼á¾4éû u*C9[èoìÊx‰láOåbú!è ºcu¬òK8Èpj,PÅØBGA‘¸WÎÉ#õ×¶\u;A'¸:ì‡}+jxä¿ ¬TÜU¾GºáûNƒ ÀÔ–ßÙøç}W‰ö9©þ)Ÿuª\Ž0rïÿ[8HÀ®ç·0xU‚…N~Ù½e¤4Z_¡Ãj¢lj¶U`„IB1q%‡é¨‡†ªwîm‹Éÿ)Q·Pý":«”^ éXwEœ6qôÛÄr°áfCXîÑýä¶öþ¶Œ¦¯\ˆßPš$ú&AEBÈ\ÅÂðÉ@°Ùàž9ˆä3£êÏäd¬ëZtIFºY/©ì!ƒby=ÚQÏÇ`‚üq‚öχë¡<Žß/ÝŒr„Ò{d£ .Ët|¨ÊrZv<êÛqdµã.bŸt’͉L¯O¿ˆP9ÃBZ7_E€ý]¢§lFxSê^G–gö¢‚lßù2Õ‚¯WʺÒC´;Ï ´×Àö^o ¦’méñbä©n¥qÎz±ÞÃ8ŠG–b]}ýjf’A¸ß:ŽR~,Ûi‡s½¿üî „Ðüìsêµ¥½Ò<…pö+rÃ}ïÃ(’»Çõ2ŠyD˜ºö!Øü‰q°¡œæÌ'ÅÐfÀ Ö7fåF ~óÚ@>áºW\ì·y†œDsºv¸l½jÙod^š*ù(’…"^ö‰ÔëǾ‚"ùk£QIO¥›ZeR)TZ5£¶ƒ¼9ŽÚáÐ.Æc¡þ‰êcŸ”‘•xaŶM_wôT{\*ŽÀ/Ð ^c5¿’ =÷^Ìb‘&ЩÑqr;tA„+Ï…ãò;´“°Ü-†4,¦ó •ñB§¾›uNÉÚj”ã ©ØÉl/d‚ÊQÖœíOhñݹî'ú³)^?hôto¬H·g:ž¦ ¥ÂaÉ™át —U…ÛÄzý!Ê! -¿¯Ðö¶MŸ’Pc‘ThTôÙmŽÄ~"­„»P9Þ˜Š"Ë}X`B„Xñoë„EíCPö[·™`¼»‡ÎÃ?ÑEZúpý^¤Q–U˜ŽK¦‡Ñž"àòÄ%'à?:2)GqMŽÚýö†?ã¾ò¤ü‹óQÝ÷ ÷P)Os`%”—qèŒmÍZ4¿Ç‚Îàä­—6úv{©§ƒå!Ð]%Pƒ°'2/aêAtG]ï% l°K‡OZ]îKŠ£Î"c0üË#£°q9¯{²ø;ÌñW‘Ô(ÐFù²’ò_±”àÃ&¼Ù] Í“bUv-ÜǾlÆi¦£êwÒ ¿æ;“}‡µÎž‹5ÜÖ+âj¨X¥¥Çˆ´`ÞÆÄ”ç—ýÛìì!ÉžUžRû`Ø•¥G8ðÙogMvä¾[Ë¡ÖÞVp`W,Œ[ò‹IÌS:ç1ùðwSVFÐÓdFòz^D–Û|21òkûvס¶H4·ŒõÍÂ3¶¯f²ß>Š4=,3úŒ!80æ¨ §Ej $âq9¼!þøûQ<Õ}(tþ£Ó½KŠB©î#;Á3ÍŸ>MÁÛiì §äJ££ †œÞuçÔ^®üÖŽ],úÉŽ,JÓG/g’è½…vS’|k•F9Ó&Ïãw/>ù™‹ã¢a¤Z»wM]}gùŠÈ8ßs‡Ü!h?§lÊÛœyàqƒ€èFÛ¦lz;¸ÆqÝ´ Ô: ‚è·’sC…ä(žÃ)LµÜ/Œ’…#P‘³çK9"»æ4“Ý."w«xÄ,×kiaÔ!R$!g⥡½[ÍR I ª„ n‘ØÍÁÇR!3[ÄMXÑ{EÈ=’]¿‘cмà6žÈVOí²%Dg=@‰D±†®6ì^K`‡pxI¹¬/æ†|,eaE ò ×ò.Fˆ²I{¾_ˆoS¸±ñ­Š+ãÞìùì®By×¢ÔøÔyâðc<é-t´gÐ…‘ßyÈM aÑE_&¾ByÒÒ Ð°œH\–yè(cá.ªÎðj.‘JEJV…zÚ­“ÖF(úôìÔÖ…¢ªþ>ÁêD@ª3,Ç×ÚÒx¢Öbqj¼ðò§0TÕ~KöìüÒWbxÒò‹¡ åÙ•~&^Mp†è7Vzi¼ÙÎréüÀö{Y™úM§cèSîEöè„ ±(âT BT-]o›YZ"èï¿KÑÍŸ”ÐX¹Ý.¤EÛ7¦L$u–jyxxu¢¶ð¸ì/2ö‚!Á >^ä¼ínïü/ʘžÛcP§»!-_s´æŸ±›øÐä$Á[­EbèÐêïMJÐ<Í{ð"÷<Y¢5Àu8…‹¡¦d%Ry˜â ¯î® ó¨á³’ˆÚ[ÜϨ‹?ß¹GÑͤ/¶€›[¼Ÿ4£Ýø×¸RÞ7×TSøulxYƪAP*°Çµ:j-°|‘ŠÙ ª IB9Ù¿¿_‚¿0g‘•ƒŠ'wåzƒu C¶Q“gïmcûøì@&ËÝ ÉÔ ¸Ý+ÙŽû‘]÷ëί)Û×d>k]!0È~eΑ¦¢ñ>Èßê<Ý`÷h…Tã7Rkâ È›—¤œn#ÐõR%U¬kóß?à»icTœí¥¢4ø1VÑð©Hò°X` |!@Æ9ÝÆš›ib½Àê'´Šö¯ 0ç`Uaêî/©å­€SBÌçØºÙwÔ“+ܺ-U1™QTb)õ‡+üJ£zZº_ITÎî‰ù}>MªÉç‡8B̨'Œ}µ€±|±š«/ÖéʤaýU¦‡Àœ[^“ÕFñ•­£Ÿ·|0Ã|z­£´ÐÃïÞ6gÊòþóßöV>Šåå ¤Ï íd@Ö¶(¿@Â'+¤ä†jDkÔ¬t35™°ã &#<ëvÓ''N¿À“K½T#Òó+WUýd%ÝÑïå¶Úf$¹B1©·iŠšM%ºÃo¾´¼ÂÌSõŠÇ9&+ë’v6½ÕOõ¾®÷EÙaVÓŸÑ!>S1QÂ|A t]0ò7ߥ«/‰“ö3ÒÝüu»ŒùÖ*Ú÷£ž$ÒåÁ0çëƒØ]èAFß¼rl(¬j²Z@ß¾qõ«­uýK»¥wpÛ·‘¡ATô¬ _eö†ªs¦s+h«‘]çÛò¸`ÚìÇñ€×ÆDnÙ•DïÊïk ŽdÃ;[{iƒUÄ·‰2˴ᨎ¾€çæ]?Ø»¾3Ž'-xâZ,Ò ¹YÆí” ÷ÑËÈÏOfv包®Â4’ù—‚Q0¹mÃú—aRIðÙånÛ£XÅR§µƒºAa²tóå…e©¿Q­Îå……GÌ×ûáSVMoàô‘ŽäIÞœáwµì=®(P¬ârÝØg|ðñòdk“í× <ÍʯßYެ¡‡;–Á7%KÀÓÝtG}ý¹C¡Aôd±~4ga›ôrW±XÆòõ'v8RRØsØ=/ƒM^6“û\V2‚&4r\##ÄQõ­[´)iÓEŸ•À­µUíu³ycåjÀA¶K[Åš ÙÇ_häD<åVq‘ uH¢ùôoâ;ìኬ ‰ e#mÚ¬jê¡]ý§/írⲺ™Ìz2tA¼·‚:1?]BZ˜/8¾ûÀ@¶ž¡ÝõÌçÆç`A‰’ð\‹íoÙåó9¨4‚àƒH5ƒIJ$ìgÿêóy2<-».Jö¶6èq@k<>˜½ûg¸ñÏ›ŽN!ßfPÄ%3ïøÞIþ r7Áeè^ÖscOêÌ:M1zÌçJìè!Ÿ´tªÑÚ38©ë#‘o?Ïè”g@s(…¯âÄ1wü£‰!0ý"6M侪³ñÂŒRFZ;<ò¯¢œè­Â÷δzœ·Á6û¾›g¡LÝò21¶p‰çñKgoŠ&æzñ ØAÕBÖù=Ís~Vñ¢âbcàYÆY­®Éªgû¬£*h\´+ª›$§×fã_Ø«¼bgÑÛ†xò+¾k½U}ÁkÍÉÊÛwÇœSܓەŒjOAÔâ¨c÷ê¾,`b“_L…xùÔuiëUÃ]IÚhþ´Rˆþ:iætQwr?sýEÍÇóÒ«íWª:&u Ã›Œã^öwEiø@¬e¡WÖñ–48pJ¹ääùÍ3°6:ÛÕ4âÊ„(áÓè©Ó Ä¯QOϼ_¬lŽ/ &€±ý*x.«:zž`þf­Ý(Aáî€û‰`Yç¡nÚ5ó["1Z%±g¡!^o"¥ÿŠ…¤9ej£[|¨ÐÓ7¬ãgèÏG؆ºTè#rï ŸÉbÄgXñ Çä…j—ÓÁ(cµ¬š³|¾kQ}C?ú¡õ[ƒUk÷zr®™*:DóÂêë˜þ ]óëNÂH,€l»õ$ÎÍìõU#ë0å\^Âô OMÐ¯ÚØfq:¨‘³âuVÐ1ÔœnG+…ját°ƒÞ`ßåÈb’éAšŽmê'‹/gϲεÝx(vÍÁ#» ´’)Ïr[†K"ÈÃÚÑX‘ý¼Ù5œµrg}–“ál¨Ã¡\lKÊaÝyy-“qhÚLu4=_å’î íûößo?q¥Q=¶[ÊZɶXßßWÀhRqyOç‚ðÛ,ùbä>Ô -µ‹@‚„ŽH@zųªÎEdgˆ6ŒRæ°Ža³/h« ºÆ&êl¢ 'u¤nt6)Ž7Ìeµ-w ¼…?5ôÆÀùÅYˆ€1ü´å¿ƒíÿ¼C[£m*ÊPIFþ•ïÅÒ†®€ã§N„ "”ÿħeJd¹¼K÷5Cœ„nä™ó‡l<[ð"¤® åÅm±'ÆžÐûàõ¸Ž¹”Hn—ø/B-ÅšGÝ×$!r ?iŽ%+ §?•ô€Ýì®N¿h;¡ß­ Š˜)÷³zÀšH%ÁŒ#8FàˆÄrŠ>K2H@;Çw‹VÃÊŒñþJÊn+̈́Ջ(*üÚâëR±ñàÜÄäÉC x¥±m´K寅˜*Jœû9±g€¤¨›8Áò•2Ç(^ǬÆ~}ÖŸ±¾Í&„üÇÙÓÍø9Ò8e+—y`5Õ®áGó®>x!ßœõ±¶Í~¥z +„¦í£Ã)± æ2V”(6=ÄguïÓmH´V]Ã7¬ñ¯PqÁ`¨ÔÃC¨ "ÜÂ.m-ÐõÙ`\í=¼1ºÁ30å¡«åÆê=/gäAߨ2z¼s´PÒq\Uv§(RŒÀÊ1Ä 9œRÐõï]ÀÒ$žœ­l•»²§ZæUjü¸««Â¾j‡„õ ’FNŒ.î©é¸!Toµé»ðNðîSε¯šä"¶EjNt Ù´>¨ú ;’Ÿ;Ä:à£ê—µô õ~äôV-`þ g"Hiž¦!E¹AÄ÷CµvªùHaLã^è„Å d"õ„.¹ )ÒöÞâös#Ù¼å¹)™Úçë+TásÖÖè­¬éˆì÷‡Í ‰t÷¯Ð»e~‰¼ýˆ5yé„J„´¼¯u¦õd;R^UñMÉD¬ °“‹±ÁQæ¿T½K„5Þ(ßÛX°K·=&‘˜\mÖuv?n}yô³à+7Ž ÷UDzÏéÍ„öŸÉõUÑÿtr¯*¼ÉU^à›Š«”ø.øý™ùß.Ñ<t{F†õäÎjI”çê̬å¦ý3'F2_­VaRŸ¸@ÊkJ5—OêútÒ‚…ËÔA6óý­e&qÏÌ ~sééÍ/·Ò¼Õ~׫e3$û³Û_p´0¯shëzà ò”ÜŸÝ \õgŒNH½®ñµ„,{Ѥ"vØùÄígÏ-hò,‚Ó|ï¾·uêd'ôÜ:qG—›·Ä؇êŠëøA™¹§ Cƒ!J‰Q_¼#n̾{;)ùþ¡xŸEëÃ\96S°|IJHç+>·4ª:H!7³5sP%¨Îør ÿãÇòÕ;L=gð¯zï{V z’Pò…ÀWD7›{ønÑÝ"6IgÉ |]'Æ{½«V\FÔÉ0°ÇZ·][M'°NÕPatãoñò[NãBb‹>Ê£ŠQ3&v«íãeÒó$QšR½Ú‚×À³ŠüÏ£žüV/_ƒD“Á$AÚyu"¦‚°73öN{ËÏ“åH6&ÏA<¸ˆ’»1y¿] $™ž0‡#¶9çâߟń -½7¥¦@9ãYüùyÍÁÛÊ-ïÀ˜*«x•:_¦ÖΕá)Ì‚´…”r3*š4³ü¯Èɯ’Ew”:.ƒù0öª{ëG3ÀÞ˜:¦¢šü]HSøvÈñÖ—¡âŸÉqÍ–#ï ÐN1iÐe.î %~bÿrý‘b–Eƒ8Œª'”Ó˜‹N¨Éƒ¨#XU¤”΀ 6ioÿ¹fšŽ%J~Ñøœ3"Ü>ËoÅpg£= \j u— R­f,BÀ€Ä[õ=û°k‚£þΩвmà•Lâá„Õ7!¢™8‘XP×u$Î'‚»Qp¿Cý“[UÚP©á¦ô«V{½‹• %Æ»W‡áhƆÏs„ÊônÜöñUª*ÖB¥ÛOY5»’s,ˆ¹ÿ6 o.E~T…óó_0›ë-À8 ýiš‚“|WÐaŽù>9ƒ¨Ë1/&5 wD·?³kÔèò˜pH¢$‹ ïú.|'ÕÏø¤^ÊÁ·žp¯ 6òŒ†¥tÂ…BÔnħå2€Ú» sÏ÷W1Â*´V °y¿†9¤Í"´¡þ(~"¥OVèX€­="¿%j.SÀ–Cl‹'èg¼ªÑ8TŸGåGh¿¥t†Í0©»-nõ¤ºh-œW Óêó º7/|„™Q†÷x¦n¥émgó FÊS÷*Z9“ÖC®1iš^½ò8Qã[dÌák×ÆÆ²0·OÙóäêôsž=¨7Ld ÷"Î;í@Œ¼éü$4%-ØÿšI¾”Æãùsdh¨+Ø'xÁÉPöÔÕøßk#Y²£¸gg¹4¸<º~ES%úy‡¥;ÐG¾ æÜ7CÜ$§ˆçÔKØr¶LÙoÁì[r¨¸qëËߎx™#o's1¾Tú C¥Úr|3ô~ÓUE.ï5¿¡ýY‹Dp<¶ƒáOóØ€ž etüÎþëRÁ”«°¶D÷©:,hÂ%àysHÅž• endstream endobj 834 0 obj << /Length1 1402 /Length2 6034 /Length3 0 /Length 6983 /Filter /FlateDecode >> stream xÚwP“ÝÖµÒQzS$€H ½÷ФwiJ $@ $ M¤(½w¤H—.Hï‚ ½‹€ M:¢4ù¢¯ï½÷½ÿ?ó}“™ä9{¯½÷Yç¬õÌ„“ÍÀ‚ í êH(, $PÑ5Ö ‰  ‰rršÀ0pèßqRNS( C"dþ¡‚‚‚1¸˜*ƒê"-8@X ,!#,)#$’þˆDÉTÁ`€®@ ‰€¢I9Un^(˜£7çïG·=@XZZ’ÿw9ä EÁìÁ€.ãuÅM´ÃÆH{ãõÜrNŒ›Œ  §§§Ø-€D9*ðð@ PD\ ,," Ä=øý³Ï¿Nàoö¿£`ØŸÝýGGM„ ý ÜéýMäÑepÿ± àŸô8=CÜÿ–ÿC!q!{Ü—ðÿÙ¿KþÚÿÕå•ÿïHÝÿçþ ðÿäÁ®0¸×NÏœ7t‘8‡ þjýËкPÌÃõ¿³š0Î# „#Nç@i1‰¿Â0´: …À0öNIéï»À€ÃP$öëµ ýWç<{Ü«»±ß)(ÎXÿ«†°GB~9PD\F¡À^¤8àVâaœU!Pìo…H ®€£èp@¢HÝ«¨@‚„ÃÁ¨_qÒô¶÷@¡pîû­Üà¿×¿­…b¡ö¤3“H{Ù`çªà¦¯A7=«C"b=ψÍVÔ˜­ªÈŠæ…OƒÚÆ¿„Ÿ,Ro‰¼º¬w1§r±þä›.C?SÓtÍÁî3¿ï0µüéZÇCä‹vk«¥­(âH¿ûƨÏóHiŒ‡ß}u"cãžÜÝ7åßËœv‰¸ê¾ ã E†1JI‰’ã7ƒ2šË•+Acã-šwÐJCÛñ,ê'©Ý"âË=³ÅüWaK©777)Ü´26RÖ;$˜µm‡cœ+jŒg1ÜGMÁÜvè÷ÆŠ²™š+Ã;™æ5”—#Ñ¡':ü”d5Ò\ֈɷæúÚ´m¢+ºÝ±º.á»ßéz5Ä\l'ˆõï[4F(}”qÞ;ÄXÕãûо#ÛmìRd°¼T!ÌeX7:Wj04:Ò-{K~.8)ÈŒOñ´Px:ÃB®ì]ÑíD/2¦üØ Ð\yGjÅÆŠå²þLŸŠØŸVÇü’…"µP¯.1„‚JïŽ}„zÏ‘ÆS¶ö”ÉèÄT¯W]µU+9ðÓ GJèÈâšFVBö0,uWÏã·6õ#¨É¤;\°Ô«²{Ýx5wqÎÙè²ãÆæ«Ï=P3¾‡25ž;Ž™Œê±Q?væy ?šŽ;nCA9«A7”;2rô¿·Hé®éH>O32` h„‹n…–Øù‹)6ºQˆHºåCdÄŒ]àµèÑ,?¹ ht—™G“màGt1¾R™KUZeioîÁB[}Vó¹Þü7þÓ{0±šÃ=?“o «ÕëlDë¢aýós äk&Z˜Gé>ekݼD‡Š,‘2cÞ·Ë.o_@ª}*¼ºéÇÔ#΢Ó3¾Aƒlf°‡±7–äN-é|äéà¯àL&KK^º0rÚ\k)ÒXr?³{ŠÝIˆòŒÙùúZeÝÜ注ïªKRôÉRM”ȵ½Ëù…Æ7¥Ï¢_yrsÃô Ã11¤ªpüË&jB­æ•€¬U£K×ÇŒ™Þê´ždJµ½—Ö3i6ñ Ù/MEZÌá¡zŒ àÒ3y‘s1kÆf / »,=­%R“0k‰ ãl©ì€Húh“ð’aÒ§ h·³b`üÖpŒÔaVå.šþùñ”b/CD—šU´§Þ…sº^ðJÁÄåS²Ò•|D¾ $ëP]þŽÀAµ  “˜{ ÉÙ²ÛVÆ&õ,•ªV±ï£eê)Œ/5a’9 ™HìMUÏÜ1À¹öJ}nQ—Åh¥7Ù6ÔØhZ~OL¾ þ“[}3,•µ£¾õóxDP-D,:\j1Ãl× Ýy–ö%–,;¯ïv«¾Øšâ ²… Þѩ΋¬Odd̵Ó[N~V+Û§î¦Ë‘|Ügjˆ’\[]ö5w úúƒ^ãw£yùÒ.ÂEÏÄâ;T9•ì¼þìÆ—=v‘ó–]…+Xý¯\ÃÈCg&2Že-.<ýÞ«ow~௔Áù?©=˜ìLÏc®ÖzJ`u¸yj»Þz:À@êþÒµÓ"‰ â•8™¸<_ÿ“DœÍ?æ«YÚ0^Ûrücº‚…ÃÙtËO×_>GÖD—*€ˆ®°ïÊó­o‘d·äß¼#ò“,ÀÛtº‰êÍîz«¢v£²(Q}à%×O2®ƒïÑw>ï »~óX‡¾Ëc~m7pˆ¸M]ô¢û H*‚þ Ù[gu$Ci~ØáÙPð¬tshóVѨ0 !gýŠl­q÷ͱãDÍ{¨§Í;|±[,yooUÓìÛ—Ó´Ÿ—‚$™¹%‚Â^1ÒhWR´Õò–NÜówæf_V¹ö¨·ÑÄW˪¦©ÚlLœ:¾û^²Öò3¶úZôÍN?Ãn*´„¶gulò¡ÊtFrF¶§{/„åFîÁSLª'›ñÖÊêžÐ˜Nówi\ÆËµ¦ ‹i†tvûû®ÂQQ¶–¬‡<ô3›“Ѧ-@®ÿªxoéa±´³‘‡g#L¢¹Û%dlÃZøòf×/0è5$ Šé¹×ÂoL“5û‰ƒÂ^íÝ=|Ëí [£Q™ÄÕ1Ï™ §ýr mÆpdÇÛlÛ¦ü­ËÀðíúy¹KüÇ•ôx%‘¬àJ•ç¡üȀ瞥ÌìJ@ä®ðõÙR»J.ûï' S;ž*Øó½cþ±ýn9©â‘Q¨*k›Û­ŒVrƒÀR¾<£"ª’-=ü|Þ8s|‹W µ¥ˆðoÙçW­a Þ Ð‡Çô?íó307Õ››—¾l%ë‘çÙ×µ#)›Þ”Ê+Ë%+r”kž,ð2¹ËmB_ê¡g¹<ÓðûÏ¢>ߦ{C Û$ØRÐ’6ÜpV¶dÔ¶$G[öi×~ƒ»ß¡ÃK¹J{sZ®Q¿ÆíCÌýHЉ´gvŸ O6ÐS1¼¹híÃ^úÖ8êÀøEö§´Ù¶¡Éý4ûúºÝú•nBZt8+„rªÁ4}ãDŽ»1XÉW:!oäSJç)ªíTküE—©ÿ¶*¢WÚ~t’¶|•©¡‰Ä¢‹×öë‡Ö7Éw~ô K“WÌ8M4p6ÜâxTÙ*Ù£J¿ýõ8ë«~°ŸsSÕ4Û”jQÿEÒàýÇU ‘¥[Q=þ«A× rî÷¬w+›š²L_µÍïõ¥‰Ô,út"{‘_zÌg<qÛæ“ÉY‘k9ÍéƒP(©T/w.Ñ”@¬R;è!RŠ\sÞ9ø)'Ê·9†ó!k‡Â© ™ŠÑ튧imîŸìúíσ™ê çƒDnæµzÛ¬ß yjz^m0ãßÿèðå¢S S«T—Œ"´#jÑ@Þóp#®dûܰi-óJ%™ »*êW<%±&~ðŠ„O,Ô¦ð8ãë>¸ˆu«¥$UÎúØ®úe/q;üùLø>½…¯–¹6-¹»cøŠ‡O“ÑW'ÀÁ•:¬ºN/ó‹#Úq£’4“b}“ÅñLäçVr[äþ¡š4¿$¿ŽsÞ*Ü6FoæÖa®åªr6:»€=B’·¯€"u¯ ëhÛ¹að2ܲ«¼µ Oñmá»I‹«ìÎΚbŒ©ù\ÝÓ÷ 4Òõ²âÏçÒ_ˆ —zòÒʼ}×!ç…uø:Ô­o2$v-¸™¢åÚFKÒ<ó€ñ½óÖëNc`¹LoF¬ ^«âë›_‰‰î«¦:YßSËgʪ³f™,¦|º[ÕXž®D2x9mqï'Þ„3ßîQ“œ<A»8ß+¬Ñ¦“¤?È—¯(5˜V&Šô1“u+À£4 5øo¶ŸÍ? uÎvzr]㪫l`Éù¹î8Àþ&ÝxJƉ9SìäÐBsØÄw+î‰ù8“ IGÎbÓ£‹/¾……Ñ)ñÌUÙóW»6b×}àÎP’wU‚*ÒHÙèÆˆÇ=ØL›X Á}_nR™Ä¶ÈéUé'¨)Åp´Þͦì¶;P¦ñôÔBË{+a Ÿ½ý¶â­ìšèm4­hÆ#EÁr%nSÜ0±Â×wfœ1Ö£n-P$®iç m¢ìo>@Èÿd§ýà·y×Ü´£+O`°"'ÔÀmç{õ ž.žú¦*âßyÇho”Æûï׋å\5äW½¬Ž$iD%ÇõXõ¥kú»JyOI-*kÛJ­çÄÓ¾ ÕJÒȳ¤‡¦ïÜ\ŸæÑðZrøL ïéû\+½qo´¢ÇÆ,2Â.[ÛøÞøX9ðqx·°žw…½A½Ðï½ù¥rá«Aå\Ýáë) Ü_z[†ÀáÞyŒ½o­MÎhã ´¼Æo§ìxÑ µ-àeÍÙï)OLdMê$ŒÏâ¤Ðà¾ô~ïNÍõ8ìÏ¢Äõ07³î=Fqrºá± iZVÓé ]{6r”D}Ú'44H~µQÓ©â‚bi„˜XªÛdÜ÷Ë”°›Ó÷'Sê-€g~H戭¢Ký~éIJ‰ÇçãU, v¥ªhÅî72M!¬‡§iŠðnL›ó“…é—8Ÿd¼ÜJYãZ¹«¤ó)h¯¿Š¯]Zß›Ÿâ,°FïwXîƒt™ÍZ:ü*û¨wÿQ;%‘Sj "°Œ!æ"½?S“/²>Zðäõ±[UÞÐ`þä•ã 5ñã•O4l‡œ=¢Ðú3´1Dw†4¼e¹e>›cÓqÿ“¹Š??®$GˆŒ„dw*š•GçÏD;ÛU¹³º(\qñœ"mÀÔŸÇç’Ç=¿Ø H`Ø•÷·Ù½Ù9瘝iq>˜!l”í۞ŶU‹× †gêì\3N­& òtxkb>ookr0lÊEÌËDVÌ@ßjoœBŒA–ÄDú¼*³ˆ‚¸*fé‰âïN’KÔÖ”ðpJ¡˜/šn?¶V“héCr&F~Í€…ÏrD6÷Z1ø ùÅ/Éõ2ù(A4Y™çO”Œ*¡“pYÀ_VÌ5/zyÛéîMyÑ}&ÿ0Йq„¿ž©i}5ì‚2Ø4ù=–öabh–gçÄëÈ?çÚÖïFËšI·lŇ…Y½å?áN`ÿB˜_g¥ðâ¶k“{h¹HùcM¶ò º£‡‡z¨r1­ã}ÓZü„v”o¾•°&1a;؉÷¥ ߘŸ„Ï9f!”BiÒ%ôç±Ã®AïÃÑ“­¸òCe_$Œzr‡Ï…ìÁ<ôZhK…¤Ü(…R²»®µÖ»ŠyL")y‰NÊIÚñçMø.ÿC¨\JÑT!=§Ö¥ëû¨”MÓË©ÅRèð7†–úVY±e*æÒÚ—)v¾¯˜¾”å¢ÎìV$ó„ˆõª—¤´¸ï•º«æšdŸÇj_ìÌ´†»{~€ž…Ç<”$ñöT¸Ïç]§½ýô¶$´–"ó»{¦ºy*ƲûÖ£`ª¼ Þ,E2Ç»Žù˜œ˜E®ÀollÖ¨ar I'œÄ¦~}BÔQ î‚uŽúÍ}Š×ÉXh^Û}•³b{Ò4úÃñûOÝøìšÇñOrOEé.ú¨8b£ZUÊûtcå›Ïfõ„òfPœý‹&û?·Žn¼ã V}&²Û'uƒºçð<‰åÜÓ0×_1ØkÆ"êt7ƒÍ>^Y™«|/ÜotÉ îKØu1™þ¸R½ÏšOõQ‹!^ó©—¬LÙmLrcz8ÖwD¡£§I0µQ““?X_]2'ë\• )ùáժϴ§l‹® ÍûËP™UþòeÝ’|ŸþþY‡aFêMöz΃‹=¦%Éü˜îê¦û,]—){!¯ÕêRÝÚ¼È/óÈ…‡mÅ8%*¦ƒÍDYØÜº—Yü³–3+ã3 v7hµæxmFf“¨õGVïWN›šZy¯¦ŠÆî1꺦–ÙÒzÊ´2šZ„=k¡’ÜY\‘ 7§¼m{h|K¦‚~ˆÁÊ…IÎ2ÜÛ¥üj£ÌjÕ“ô"ƒ(›ú–ŽªÍÈi•cfdÍQõ~ìœC &n·%ò$ÓªKpÎè‘;”´°ú­»Ë5cxãÕkXÃé úà§òѵÂUÓq£6«Wy{²làaf¡×—C y\Æ?º¾†3ú—³¶ùyÉ[§Ôw¾—V9ÍjVi_5¡½.OÃü£T“UO¡Äd?‚pih}VL7Hh`Óµ—¿>·ýþa ÷úÿ¡[;Üô·H´R\0óÙåã#l{Ûíûw÷†öå2B…©å˜îvÚÖdQ ?3'Îï|dýzaðš÷™°‹»kÜ¢­@RóáYúFw…iÂ…&>’Îëp6Ã1¤@^Ì£º·ñïhiFüzb·ç‹˜i*4µÏÐác_È¥o J0¸¢«h"}ùAXèåjaÓˆoq·ÈLÝÊõPˆÊôNÞõ.¼K1Ž…n´ýø­ëœY™—ïAj¶F¡+(Í‹IŠ‚3*þvêUBw_ë=8)Q CN½ï$g‹“ÓdÖÕB\ 8ËŒØL'|´ÏªSóÛÄg4lzç··7Ê&_(Q¸?Eˆ±°Þ¤vv OìK[Qf­§YQÌ—Y¶L±ÿ.Ø;;0v¤$Ð>á>³@)³0}w;Nè]®ØµÆQ¯8tâqwæÙêly|’óõæçûÆX%ªW_ºIæM>“h\m«úÚP +»$°Ë]íyFù&\ÜùǦ|`ã:pYüãpšü"öº(@û¤îwÙüƒ§É–Ú²ÍðïKõü’ý§ ¦x2ÇA”MÈ£ ÌS‰‰gÄVÒ ´‘ vÛV"ÖWb}; ¦®Õø® RYq³oÏ]5­ sZ°òžðãéˆ_’ËBÝèF-±g¼ÎÓ³PrUQ·®>ú$F26,1CÎ×{Óäþó‡RTÌöä?ðÐu†2$ZáeNC ?,MËô§„(Â^Íží‹Ê]ε à­Ôj4éÂ¥îv…µÑë½VÑ|x‡þMø]Òå°q‹¦“Àèó¯ê1æ ä¥aƒ¨$¹¶oMeß÷&5¸ëgO§S¬nd‹ûYFɧþ#W”î8Ýú1`X2ž<ívîdñë–áÉLýFjý×£ŠŒ°@Œˆ×jóm»/}+é7 ˜øÝ¤—R"Îð Ñ&‰.ÞZÁ/±â £öî«@–-[á¯Ñ:òwb¥)›Uºq¼©Cæõ§X5½l9núäóZU}Œñ‰=ŒÿÁÊÛ‚¬HHÑhã傇„|ˆºP…"¬X}ñ¬ì£Pf´£s²úryÍçŽå0n_7ò6®7÷hlâ7ï!¿†=W!tð 9Nò"[ø$/³—ç×}žÒ5 i;ïê9f©„Ä 8»]6ÜCǯEtë{À4¢@ݯkýñ’.‘.³}]Lˆ°¢™™½Œ©W³f½dÅÅRÂi?¹eEØvTÙ8Œ·ÝoïÛa_,¦_DÏs¹âݵ¹ÝÇ÷çl<îX¬.œ’Ù]s`çJyï-“Í~Ùåš0 J P‡IÏm_„ ‰Má’©ûkÕøóZ§©º®4îe%»| 9½Sh ¹]SºžÝQ±ãR“ß\✰ê9v]zR쪭ç8œ/þ"2—*·5w9È×á´ýj¬“¸/½ ‡‰”½Øg'›òk‡”eóKÔAWÂkš5Ž{ik%”àCÄÝINø—É^ÒW½|¯ÏŸdE°kJCW•Pa‹÷'Øl¹š’úhD9[ãûoå1¥Ý P´¤:ÒQ9z<´Þøzaą⢆@ªE§…*ÏþÒ˜¿\Õ +¸ÙBxE5üæã¬­qb»AvnÊ{Ò¨­Þèj‚hÛgÆ}#½\Ÿ%t| +÷ô¤ïvÁ¤_xÝkbª{]ï7#X4@3\œOèÜpQmppRû¿)ªÑ endstream endobj 836 0 obj << /Length1 1470 /Length2 6400 /Length3 0 /Length 7394 /Filter /FlateDecode >> stream xÚxTÓ}Û?% ’RÒéÜ@Zº»Kš±Á`lÈFw‡tI ‚Ò 4 ÒÒ Ò*è;½½Ÿç¹Ÿÿÿœ÷=;gû}¯þ\×çúng¬úF ŽHˆ* ¥J:F …‰88Œah8äo9‡)ÄC"¤þÃBÉbÆÈ”íÑC$ é €D 1)¸%ÿ6DzH”í½`ŽA€&Aq(!Ý}=`NÎhLž¿Ü`HRRœÿ·;@Á âÛ#:öhgˆ&#Ø0B‚a´ï?BpßwF£Ý¥„„¼½½íÝP‚H'Y~€7 í 0„  ^GÀ/È]{7Èh‚Dcgê/…Šö¶÷€08 A 0.žGˆ“`¤¡ Ðs‡ þ2ÖþË€ð§9 è_áþxÿ Cüv¶ƒ‘nîö_ …Á!=UmA´š`püehG!1þö^ö0¸½ÆàwéöU€=á|(°ÌDÁà¿0 ý ƒi³ ÂQ éæA QD¿êS†y@À˜¾û ý®+éðÿû…!¡¿`8zº ™ `=!Êl0"¢Ëœ h€(PRLL€<@|ÀÎB¿ûºC~+‹1ýÝ‘î($…`>ˆüQö^ÚÃèÿŸŠžˆ@ €# Œ8@œ`¢GLj!пΘù{À|–@ ý@à¯×¿ž¬1 sD"à¾ÿ6ÿ=b!}3%c-¾?ÿ¥TTDúü„%’b@ˆ‹‹ÿç_øýo©¾=ìOuÿQE$ÿéÞß@¼þ0ƒûÏÚðþ™A‰á3Àýoú[E`Ìèÿ¼¿]þÜÿå¥ÿW¤ê ‡ÿÖsÿeðÿèíÝ`pß?>{¢1»¡ƒÄlâ¿MÍ -´ÄæéößZ ´=fGNž €î ïý%‡¡Ta>G}ìü—þ&†€è#Q°_÷Æ ü/fõÀ®˜»…Ùo³YÿÌ«‚#­ °¨ÀÞÃÃÞ—ÃÌIàÂìª#Äç7ÅB‚$ãÀ` @‘D¿ 9`z„¡=Fþ—H †y€áð¯1þ[! 9ýºü ‡ž˜‰ý­„Ü`OÔoÁ?Ê{zx`6ø70µÿ}þ}]@ >0Ñü ,áRÑqY«Àà-°1‚¿¼Ò›lÑ#Šæœ}êï¬M£6ùPÑαúÎðcý¹ò¨‰™ÞÃËQ«×y¡K™êh,•¾5ÅcÂÁ¯§¯ ÌŽHz§1ñDZkG)Ldv–x–\if3W‘â="[/6Ÿ_w¡¶HîÜ%ç䬙 è…ü®=œG¬ì+è! +òÄÛ–YžÆ&c×8`‰Šñt_}×,³‡>~|›×ß÷Xä¤H«·F¬:Š’ŽÊO“58u€Ž:%Oó% ‹SQô\©<#™®Ø-Šs ×N|éûTQ{Ê€ˆg““®Rè-½ wÍž HÑ™üž¥FÛõ\ã¯B$wZRcùk³+rÔ8beÕˆÀ zñh˜ø ]‹?u¦¥eÚ8 ÍñAá"6›ãw.írR@ÂÖ2p‰OÏÅôáÌîÃP³…«ûJzJ} \]V—Ïá»ü‚_žõÁ*ÍYÒgÛ-o;†z¢‘ì‡LÔ“¡Éæ9{ovS^jˆž¿§0åUC×iÍ"»my’ò“¦‚ òñôÛ»Ô¤ÈKγ%™ŠSÌkoaeéÞ´ŠT™"'¥t=,gz±P%öî©LX‹L†D0hqü[Ù`?‰¼ní–AÏ×6ÉÇB„6Z]œíJu¹4Ñ÷’aÍ{ÉWÛŠ“¡Çâ3KŠ?L‚m)Ë‚¬   ß¿l5˜+4Ä<€Ç¦wO¯Ù>{ÇÔù ?‘1ëÕø~o'WÆ–zÓ·s¼cJ‡!5©¶ˆbxes’h›ÒÇ~êXË~{펳BžwÐæ³¯Ä Ë é{ë¡î6ÛMºGîß+**n“qÍEJЬUë„pJúãǘ+“|‘¸Mb?Þ&<ƒÄr†6­Ãå´hŠö,ÙµÄQ4|Ss?>ïeüHÙVÇ(¤9à¾À-S•øî¥/òᓹžØ[_dwÝaÐÞ–µÙCå0Vü‹{Ë¥§Q-EIÓïŠÌõU޵¯…×l…[oU·–#Õ3ü‰@´>“tTƒ»\ÝžtíH’Ëóofº,L†9*é'%Ù­IS8gß9Óײà,ª?i¬‚µ)p A/˜Uó>—TòEÃI”.­%Å‹=Ü„Œ^Ðid8tìNžÎÞKCà\ŽÌ»ÃvXmlXµi]áµNþV¡U¡78™Èªq+¾~ªþûÖ/†?lÑSfÒÙÝï>g xÊsß­@ó¾+¥œºeò4Ï?`í˃@{‘ Õ28nFש„^ÁóItªº™BYOõªtë‚éÒø¥¶!ªpSdÃãE¯¶üýT¹ž†téô¼:™á²üýk¥•]Vl•_›3rh' nx*eÌãå(;Ñ‘NÉÛòçÐ ç‘uºÞ¦Ip€Â·4.õmp*²½çs(K5Õý\¹Á"á>ß“™ãC÷†Lô5 þZ£å#(úHâËšŽÂ¡}¯×Ic–…­ßç˜[´9ô å÷²ÕãÒnß_ÒçJÔ|6¼ì•2ÍßÏÞÈælRª#wÖ°'·’æÎ;!îE:K+³¨B®©‘¥É?×Mµ9Ɉ5Þh€¶Eè} J¢Ã[õx"Iª€âS›“¤‘7#ÔˆŸK5ô{Fyz Ýñ·¡Pvþpv½È?;{U1cxw&ðÛ«þù|”0”KéÔwiµÖvàÅÔ yk0³DZ‚^ü!W8Ý&¶VÌÕ=W=Úƒ•ò3&€Ô²pþúH•GK´›®8ï³yIÅ âZ.°âï_|{9:·=e…l³™eÉ¿qzbM!ÏHZ‰j匈x-”¼ºjÓÃj¼ñ&Äžäg¥êp~¼a…&´Óˆ­P:i;ãÊÓË(–HAô$[LQ†b±È ±˜m¼FXT7ÖÁ9qQNi-„?"è3Ñ?(_0•É÷ˆ1FŠ}]¶uG .®5N}šö¯ Ñ-Ã:ræ@}­Ø9Î`µÎ®è>§ [ߨ2]Xï¶/ϱ>Û–›æ'Æ98q@ÂÓ²œÉÅR~êÅxõØ–âî¼kL6Øàê°¸_Ü|ÌpÑê!vÑñZº¸áAævwÿº×³¤+±/E"M“zª¯»4½òàì Í…î”7.ula]õ1×ÁOMIŽ#,ò±Ø›u».sD,a¸ØP›}óe«ÔÏÎ÷<ƒ‰*wç¶‹¹ªz7ºZ›‰ß c 1ô8>'FÏw3ÄÏ} %vެypEÿ¦H›TbìÕÙ|xø´i I5S—«­^ü¾MëÃÙis>OÖ‚‡ù|³‹` ߌ¾‘öâ‚\l"J[wñ×vò ÀÛ¦ø× \gycuãçåh£²ÁçdŽrëÌ©ñ(¹Ã-Â#ß\¸êš5Y¼:P»¿­عãÚ°ØK°lxÀ½0=f#<ÇAÄQ¸ºÞw‹hÇŠ%Û¸…#§Þî—ߣ3Øh£®Ž(ô}B–´àÅrûˆ/(ùyó›t•&pâûúyÜTþ½Y¡ês&š=ô\$î•:$'j^_©qÇK÷p‹MM,¸dŸä  ߺ T¨@›ü*>/`«–{½ÕtúórœZY\…@Ê“J %]XÞ® Ñw˜/ÕA<â„eI0¶„ñÞ£0v ÓÜÐÆÊ^S9X÷íÛ±~§[ý}ÝŲŽ?]|sB{›LÝ6¯Ð=,}ç¤4D—ršr4÷ª-[ÒïFû†qŒÒR°ÐtP[J_VÔR$ïÁcÉø~±iG…H—“­sJ—Â6Á›üø#—| Ú™úÏĽ¹peí#ƒ¸"¡ÍúäYÇI'×ýq‹Îe|ˆÀ>Hè’4¾@<4žWEôîcÇèÏÏ‘‰™þÖJ²ì?pUoú9±ŽÇð>C¶aMÝp‰{/ û=ô`¤x¤y"‘Ô§åmàô1Á=dCI&8ód´g¯ŽXÛ46èìíÏ«K7*¸ý(‰5Õ¾ [‰]r{¹í ƒ—0Æ`úu÷Wç}‰ÌC¨TQ_Aóð$\ÆÉ‘<Ÿ7‹Œ °JÎAZE®••ïâ\>W2 €~´j/˜VXƾLÚ³/73Øáð‹˜º£Yß:gþœ¾¨G­á |ÓõLoênlŸeÚÝçLáÊwUÞ‡¥º»×¨òV–}©[Êò:òЛrEˆ#n=§˜Ä…J†óÖ0ì›K}éÚ’èÈ‘âYÒf‚âŒ$P÷J¦rÚ§ºHó1ùS·£oòŒ/(¤:õÖjñkõà,š6sùÍ?8}§À´Àsqx>v«aÚ¸#¢7;yQ{t™TsïèdÇFVvmYr,…ºÿäC‹pëgª%“èo¹X™wñ¿ŠšFìA'Lâvê‡^\MÈüŒÏÁüžéÕ ÐïÅßFåH~.eN \ßHã%bâsrWá¯å-àR),J¡4&žûeš8õ(³¦éñ#y°àŽjÃ`ë0°(m˜·Ò‡#ÈÆè !v¦§ë&Õy YŸqs?9ÔŒF6Ê×Ö­f†þ´=ÞU˜ )]5 ÞéVd6= b?–T)j£Iv‘!zd-¨Ü~âï}£Æ–LTä¢XõÐiª»áÞÅìíõÜ}…²ÊÛ+ëÇŽ‡ÉX–_-MÜk"ˆcŽ~ž<~z¡½óþfÕ)ÿŒQ_ØÙZÇ Æ§ÏK-S>¾ö²ûDÜÑT÷=ö¬;ØçBýgCDñî˜``aëè­wé/Ëh?Œu©Žd§ƒkërRÂdîT¿†²Òb³ðwVâ my㿉5”hã–ŸŸ”ãGné”ïÕåÔp{œÿñ™¬9ë[· Èç!ùQ8 ©ÙO¶IS%õíË'ï]i§SnÜ÷½ÌÓõ$±O'Ø-.ëì,é?ÂAë6¿‰ ד·¸*hXGóÐê\’7mþ´ÈœG4ч%àãg'Ms–ñÚ$2 ¤p]å±ÈVï\q¾ ¸¿<Ú÷üñEóýAíퟻó|é`Òêæû…A¾\nû¨ûÙ&;¡’]8¥ _Ö¹JtsÕVndÉ’âô•¼r±n¼81—Õ,ô“›W>‘ѽŒÄît@0%ø?¤u°à–e›—àÝ~Ô58âZæ+r‰\»Äú9U_ë!IRö^m½´~BÜÉL½çøÔ_%•z¨¸÷‘wè<ÝJ6… ;µéÊ–3=:ïÜÏ•ÝÕ•ÝúÞ^ 5Þ1ÚRø­†¼] Ï,Sþdøô»È“óÇî,pƒš§i›Ù±x+eÔBî§ØM§OÓv©NHàÙþ˜V HíFìQ¼'øY䦕èÏé'}º;?ÔídÍ&þnŒ¦q/ïÙg.^šë‡æ!ÆØˆô}†éx×!B¹ra7:žüá1èYkÍAÆÊjÑ¥ï]îµ;Žÿ òRÖæ²ÛÞÄ' #X¶* ¡XÕv…ÙŸ"=5ÅEž“ï6žx­ìvŸk-šùçéL-‰ÈÍ&%”ëœX•2£“¦¢ðbIŽ$Ϻa¾*}#B‘%õfl©9e’ þІ´\«ñó€à­—(š}Üsëõá©2æq?n]§Š6¾Š ñÑAËúÊÔDñ®…:(ávÙt¢û<ê á\Í—}%W§ØVgsƒŒÚ¡8{á…úiœâh4ι§šŸ´–Ó½…Ó‰fé—žedöxu_}Q jëÖ oJUe3¬Ênáãœñ}Ð2˜ŠÒ± MUNÈì…~Fí,„û 5­Wf+Xßy_‰é} |”‚Þ¥8.2].oà«¢(~YUýêŠI<®Á–ób¦¼ßwkcèMqA¼’蕚‡Óª þrÑwìIÑã9j“šºãƒ2>ªU¬ÏIä?Þ%)¬Á×ñÚXæv¡E—†¯-H>!>äZZ÷à¼3»©7—BãF*ÿ,±úø¦¡eíxR÷¾ËÝMÂ\a[o:@Õ”s¤¯¤YÈŽ#­t‚Ÿ€g¸¥æ Iurç‘Qk”²ï1kÅ8Eã•÷m?ï)ß"£”Ï3®JLsÙŸ³qôkØh~*z»vâ©•—KxÊrýFBRðz¦´}ËÞK̬ÒÍ'G<(Zà —<3oÕ—G8ÝÔPÝ’’ëA§Ï%ã™è‚ûI]„•Ü,‹?Uê‰Ë†ºš}s-.*ïÄ6¯á ¯?d*¡É#£î¹oRZ?«»(¡ttYDÍ’ŠGËgße ÿœ9æ2Ïp¤–äS¯;Ö]Ç'ÌvŒ—ðï³>‰wk}"Mw«ÿ3y~ûl"u±#½Ý# œ(|‹Ìó,ÞHwʳlÖl•7úOÄUåwÆÞ¸è“I®žT³å¾vJSŒ{?Ú7¯˜x&­hc¤Wž&òµ›Wñ–HC¸'¢—ýå²F?éîÏ[=|È»÷D,Y쯖íÂ$© „Þoè4@Bòåæ^ îNÖ6a3“ï;¯ãZÇ•8wß¼Þiß­´Ý¾?q9’ÙχG¾f쩨µË«‹¡Ó,üQ®'ÿœC'E#li‡]Ò4ç…5mEß*ä°6Ñ{¢cªJ=ý9Ê窱!l&) Í , ¿|Ó|&‚Žn®üÙVèRUÒÀVÚ¸yv˜q‰yŸ¬‰™×+‘w+k1ëÐ½Ž†ær;É{[CKL³‡{,wƒƒöâAª_w˜mÈD¼ªn¬êåzMÖ06 c{ù}Û0nYú6 œÿHåp÷<Û2×Ïw,ušªZt}ìh¨°oÇÝ)ïŸ,sÃ×L¶û8f]ö[JÍ–¯üfßÏV“•o„¿ÿRèU—ûgß÷Ut/‡³rú$µß/~”A(àXˆ·Øé¹¾k…Õ3‚³É–|Áåy8@Í*»(òؘ@ÛÛñÌfúEúžélÿ—zI­µz3ß„É ËzÉ|Þnï²Äôžy+:§¬v\]·çç²ÍVÀsŽÏý¤[ë²4|§­Tfo¼Þu÷(sÕ!~)/ßá|õT$# Þ;‹6ºØ|ÃÁzÀ³-än8p¹4ÿª‚íŽp“'Q– $Uô’ïÍ|-ªôÁ =!U]ké—¬O[1õôgǵFðÛ.}ç€d:z?/:,ò¥Õ AJ-?+]ªÂ¸ˆ­«µ •]þ5ˆ©ð$…Œ-’’‡J T<`úé¹Ô$½É¼ðD‹ì (fömY·YÛÓp½ë/)÷xõü¾· ‚[N]À镜WËææÆ(“öweöÄo§[ÜÉn<¿|{¼Ë¯ ŠÒXVËÊ“»z—½BbmlÔú¡4ÝŽCЦýp­©& ô „09H>6¢ãüšWE¸ ÜðèúT©Yʬ’r#ô G·Úª[Îæ×aÞ¶Cù`ûË+.)­I;owð˜1efë‡EÛŸÄçêY µ—q­ ã¢RN0ùgöÑ,þPïv{€F¦J^ÚªìZN)0ÈxÙ5ï“ý÷@ïy)óÓˆ¸4Ç6GÕén0˜ˆ­2ëVÀ1¥3³¦¡"½Õ܆*Žwb=ëõ"Û5š< aN´õ|Æ='±¯K/±:¢†<Ë„œ63=:ÐüZ(¾Ïü›mÁ¹G“h%ÐR*É4ªêX•1’ùo£õ ó5ÏEÊ™ò«y ƒ#W·HBX'©‰øÍ‹[³{ •µ–äbÃìy×ì|ÉÊò ¤o+yëeØ£®7Û¿êÓÙ¥îH”ªY@±Kéü?'5¬Y¥Ò®…‡Ù9P\Q£ð÷ KL×ß}¦òQÍ “ÚØè‹iýãÐ6gûþ ¦ú ÛS‹ø5OiŸ•!sÛOª‰_é¦|ª'^¢J;—Å*$i“¾HǪxÜÕÀaO’xq[f£‡vÝ@SÐð3×K2dIèÈhÍhdÊâ‰/:CÈ£ï‡QöϨ½žªº1Òø‰Œ€’§øtûÒ;ߤQÆ‘Ò-5æÛsV?ÎR™JXÀ÷ ·ò¯ÃS·Çé „³­¾àKÌc+úÞ‘ŠrØ•#vm íN‹Ðp]ªð 1©¾OØŒjx¯v¾«¾ÑÊãˆ7º+±)¡SAQZïM¾ä@Ûðý¬Í„íÛµäXró’›\·Q‡6RɉÙ/{ï—ù„b ­Ç¦]xvBC³… eOY‚VRÚuUx?ãÌKÞ;2-ïÞ._^*~íLMø ©ZÐ endstream endobj 838 0 obj << /Length1 1434 /Length2 6219 /Length3 0 /Length 7196 /Filter /FlateDecode >> stream xÚtTTmÛ.Ý(ô €„0 -¥t7ÒÃ0À30 Ý”tH‰”Aƒ ‚tw H—t‡ ü£¾ï÷þïwÎZ笽ÖÞû¹îz®û¹î‡U[WÆaUDÀQ¼ >~q€œ†ž±(€Ÿ_Ÿ_€ˆ]†r„þ±@‘®0\ü9È!¡`“£Ð~8@ÕÍ€DÄA¢âüü~þ‡;"ây°;Ì ÁPEÀ¡®Dìrg/$ÌÖ….ó÷/€Â=|(úàw8@Æ Š„AÀp€euBW„€z ŠòúW NI;ÊYôððà;¹ò!¶Ò\0”@ê EºC­¿4ÁNÐ?ÌøˆØúv0×?¸ÂåFBhÀÂ]Ñnpk(€.ÐSQh9CáœÕÿ8<üÕˆôŸtEÿJƒÿC 'g0Ü ·ØÀ¡-Eu>”'ê ·þåvtE ãÁî`˜#Ø íð{ç`€¢ŒŒ&ø=WæŒrås…9þ¢ü•Ýe¸µÂÉ G¹ýÚŸ< … Ûîüs²p„Ü篅 nmó‹„µ›3ð æâU‘ÿË ýƒÙBQaþ‡""Bb¨ ê ±þJ¯ïå ýmý‚Ñ ü|œÎ4 ¨ÌŠþù¸‚Ý¡Ò êçó¿ ÿ^@k°‚ÚÂàDÿdGÃP›?kôá#ažS~´ö@þ_Ïþž¢åe€;zýãþû|Z2Æê:*<ÿÇ&+‹ðøð‚„¼…Aú%*&ðûwšÿ4àoò¿Qm0ì¯Íñÿ“Qnƒ<üÃݼ¿y¸ÿ% οF† ðï š´–¡Î¤oÆ/ÌA¿@ÿßð;äÿ¦û_Yþ_Òÿï )º9:þ6sþ¶ÿf°ÌÑë/´”ÝPè±Ð@ ‡þß®†Ð?£¬µ†¹9ý·UF‡ Ü-q^¿Ðæªó„ZkÃP»?Búû(Ð5ap¨6ÂöëÆAGñóÿ— =uô­âŠ>°ß&(z¨þ]WAXÿš>a‰{ñ£E& , ð¡ÇÔêù[ß B‡Ðý6$ѯcå`p7×_èo$"Ð׺oèAøFk茄¡Ûô ù× nH$z@+½¿¿×¿o(Ô !ú2‰€H„ÚW…6žWÈ0xð~Ä[\nzoÜ)Œâ˜zéc§ŽÿBiÌEÖÒºôNšöô›ðÑI_îýó!O³Ö¬ …Tå\†Bçªì!o^ïÅI«-”ÙAo;,šöl•ü A‡é¶¥)Žéý$ÃÉŸa¢m‚eëWM®&wN€¢od¬© ¨X™œ¦¬hcV¶eTŸ±YÒ4ÝM_åÉðV4,î»lc ݅תi\Fßü|OVWgšàñ+µör‘ÒpJ:*oUÖœþÄn:ê„,Õ:W YáoroRâïÒ:…s,`;UM€Ùâ:èøÅŒöý2°HÌD¤ÖmÕᚆÆÑŽIÖŸÞ^x/Ù¥o5"õS´ÀXàQX)'dË«¸/¡i½éè™RÍ×Å©÷¡À°1[v”^÷áþ½6N¹Ü£h—Cå[šZ—QK­ñÎ R°¡§,:eÂò£&3z³êU$¾:"óИ‚Ïv'ëfrtÏ)(îÈÝu<2ZŸz¡t´³4)ë OÆgÜ1ÌÄ-¿¡°aº¬aq©¬qÙß.ò†B¹l5㜳hbU«0BÞ{ÐoŽ˜Z«Ùê{I£T¡·Ä?gvmœ;9Vd ¥žåâ‡K0@>JGŠò­ïÉZ5éÆ`Uú,|}¨€YE¬GÕÁWó'€¢o‹ïñá˜!RiT’þ^íVÐt“_Òœaê€B>¦ŒÓ¼sÇ’ºÄj¢ŠÃ -!Î\Òî­'pãë?sß%pQv¼• >ÄÉ!çLॠÇ‘”†vd´³ä\\}¯¢Å©Þ‘‡Ÿ)¢Äïáö…w>¬ÏæhÉ¥—ïõ !Òϯ2ŒÛ£ïÂ}s¯ ,ª¾d¿òÂj쥹ï*ì‘Íè{2k)h|í|Ñøþ¡| KÝ£‰•[µÂïåû]#áø?n\9u¢Öð=ëŒlDá3KJÁÃ,ƒÎTƒÈPhÖ€¬JìK”Söb ß‚©Ÿä÷UÑ+Ò™†Xy¹ËmÏÌ[Ý>éÑ,½¡ey÷~gä]ç ©\âXÊÕµz/oÖ—ãy˜$Ò팛‡oúP™A3Þýƒ'q´x½ÔwÜÈåDÒ­Rªê—YZcâF8¤+'m^J#fb­zu–^ ü «wØvi{’v#°V8œ·÷¡¹ÃåCEdy´Òëà ¥&a2\I™ú³)•wšN þ†U«Á¯ÌBî uï2Éä•]¯?%¥)1û Ÿo€’³r÷lRDîÔ>c1ƒÉ7\žDõËôG²­Çß.Ί|Ô?¹I¯jœ—)À~DðœGØ‹¿&fGYô‘ ÑûUô%Ð[Ü¡ž÷ÛJRiC€Êš€žpN˜È'Æ›R‡ÆÀ„5y–c‘éW/¤h  G¨Þ¶í)þ3 u¼g·…²1¹Éx®™t"dtö·ù°}gSãÞÖ>U¡1Zž}·ñ9šd!‹›0¹ÓGwñY¾1;V¦pïJ„Èî¸ÅnS‘M vIÒ”ÎYO4·Ã340JhàZþ.°£ å{é&°Ó ê2É30™‹Žå7©[ >]ruÀ+¢ÆôU OFÎ$’X$8ctÕäz~ µÛ>b|Ý¡IRš“D¹Ï\¢zÃX¹EL²©n˸¤9¨u¥±m&PݘMG¸bËÜÏ#™è×ñhÕÞ·ˆ@b%KË›…±¥Æ<Ù®³k¥%:£0aPpºM$],JÑßö‘µØ·KŸÓ37»iOö1¡„ßÀf|fÙùõˆS¼eX«ý‡qv1ÓÎ˨›ÚAQ’Ú(Û}Ÿ1ágÿç(%ªY‰HÊc­w‚„Çt…›6wèÞ¿×8[\ü—  U€YH÷ºš8b!F{7é]p´2¦•Ä}a¦Ï‡gåÇ)÷&H„Ûd4®ïµ/Ž`•èaêÙµ-§çW%–Ü£\xåáÃŒ&ù_«gjWχßj|Æal|idqEV¥2ZU¨åü¢P¸%üš4\v‡½kúáëùO·MX¨§g$îW/sÈq*‚Ô¢…è´ð­Æ°FhØg‹:}ð¸˜]kÒV\ê•“Kϰ£ó$Bì“ÝGïôúìß]ô™ÝäpàQÖ";À­X¼2,º‰:ÖW 9ðŠ‘.s)áÄ_8|H/„‡;ÆÄéЄ+{re^‡Ðû¶·0` ô¯d” ˜'©:ÞÄÞcw Ô¨ Yò‰«u™Æ¸ÃZò9`Cø1Ô£.†ñÑSã÷Ì/Z¾ª$Ö‚šR[ºÃ—¼gw·A‡oI5S ÇvEFöÁ;ŽvIôúµ+umæÔLÙ}æÝ'ÇNP,å—-éX›˜à°éÇŽOL÷8´‡JóÒH1à¿Té¥T]çÕ•áÖ~\ÇêÖüì°v«o¶}Òç)4)ÿýÕ›÷‹°ôæø2 ß…È’¬ëˆjÉsê~ÂNqu)7š}yÂu•Å3þ¦”Ê Ÿ[r,]YkÞ3ÝÍ›ï&E‡bfÚùÝWuéM-ëk˜c~~ŸéäŠåi÷½|þΔŠ"¨bpóÆû»ùêåä=3î!€Yn}ñF*¶ûØ+)˜*G¿ â,°õ‹×û2AcÀ[UÎ}~aíB5TiºÕn>L9I¶ÖˆüâEKÛ‘@:{_?±V!iü4Ÿa°¬e”}³ÃÓÓv âq9½š”ø¬)†Së`‘ ;N&ÜHUHÃ8óí]>Æ&cŸo.ÈpûOå£r3÷Íô+·ŠÃ>ª#vTJå5²Ntf¼ˆ0Î`ŠÞñj­Kæ`0äôlúÔ¥®+Ab$ØÎ(“ç#cúΡqÇBM4‡>›‚‡¼ŠmŠþÉ÷ýv3·EfØ­Ò¯?U‹ÿôJT'‡mCUÞÓÏ+Þx:뜥<¨…ih¾>Ú¸†¼|AuÜÏ`kX½J©–(É|MvôéÕÍö“ŽR-$ÓæWÞ(ÞóƒW(¢Hûó ClÝG¢Ú:!_…®2ÞëâFj\ˆ|úÂ<áv'¤z‡óQëÊ{M:U¥GøÁÏò¸1à{½õ³Å5Ül‚ã)²×eD»äþë g÷s©|—êR4…ïRø“ôè¨ß+…Ss¹È[ûJ$ñÞXuIµ‹èíAÒþTxò¶£œýÏîô˜ZBÝ]I˜iØPGR cÙ¯Îæ¿K@Cg'øºÌ~òöaT* ‘8´°rc »“mžäP}üÒL©YP ÝiR¥æðÓÜû8¿,»_Çzyñ…z’…È"šzá ÷PD£­t¤&¬õXæMÇ×Övmy&w™{ݦá`£óެÞÊOCº ×/æ È3ij±:Ȫ×;=šÁ¿k ¥,]gc¯š×EÒ,ê0ê‘n¼C%/5yQÌBŠù½M¥ÿ­oçPhY]ïT¨l‡ïÅQÄǘ…ÉdI¤í§EåiÐmÕ¹zÚì:ÑØ`Çx“<±“™jQ¡Vý$í,犬¡7Ot[*R;ðmv#ñgyRšb@_Sš»¹<†Þ÷{Ýô˜²¹‡S\5εLâ§O/ËaS7ZíÖÀl2NÂÎc áwz:ÂÃæ¢…Fè Ä Š3ë_eº™úÞâDZ7kš“,Mü‘)iZ…‹‘±û˜Ô㘫C¬=è‘Õú>·þé#ý€Úγë£/F‘÷k¢,õ/›W–ûÒ^çßm'ì‘yL ÔcÓÛXæ]}RÐØÎN´ó ƺÖr™¯bà•fBEE¾…ë:I™èF®»Üåwupñ…“’ ÿ‘n»èQj$ÌbsLW]îZJüÙ®–6lÖg¦¾ìLõÖIïtõ®e’g¥üϬ KçbFžÀÉ­ŽÊz{-^Má’ \LƒJE¥¦ÕìO)Í»×Å)QÜj³?:ò#̺Öø*öÎH—™ Œªõ «¾Èëç¦OÉÓ÷èpD”D³Î€_õ•¡J³Î>™"_¨1êÕ[Õ~éÔ#öÉObea¤˜§á£ ñ[$šâ•íã h_ȸYMþÑ›¹ bh÷ÿR/©!ú>ðKxcrÛÞİœ ë†«ø€_Žß§Á./8Þsý·bB ”Ø%kþ‚ú"d¯‹‹o;~Ë¿%€¨­gÍå)'ê²p‰á o¯Ó"³ÍìlÝÒŽ¨!¼fd Ée–5(Éj}¸dŸHsë2)&JÿfO˜Y,*)»Ö‘b2+éUSÓ°‘B!rm7ØW;Þà~ð hW]­m¿Þä³fIBÜ,/wêaAiG{úXá,Uªdɼíå‚¶9Üûñá ñSlËRÄCÎÁOÒxà ÇÆÜtæÝóQ©gÁj8Ÿˆû‚keF|«±”xôe£·²u×§BHµ&dVe?8¶ú¬»:Þ¥:}¬9ôÑ[$@×Fy)nâuÂ5Ku2?Óaf%ï§ÆrÚ:¤¶ê°BæÅv¹«ò¨–Ø¥4Jœ°Â[L‹óžb‰Ö)‡·Æ{ðÞ1B“K)u„$…U$–™JAzŠZE Al¾ZŸÔfzò$Bø»\Ò½Q»D²'·;ßYg ‡§}Ïk|²1zô¿ çé æšöšv²io8A#GBsfùxû‡K¾>u¬êjî=.Ë»zAMu-9¤ŠµÃ«T<ÚñØ› ù¨q¨¿äðÌ<Éy¼Œ&79®©©™ƒßõBnµnÚA¿,ç·•X³õrSä”ê|›ÍfÖ¥þzpÒ#o-g4–IT£Ø¹­ì=ø†ª`‰`0?"àÌ&²’][U‡¼d6„1é9k·É,æ³ Rz~úNï9 úc@*¡Ç Æí^z"Cr™{yÖ•fkæÒñöÆ½Ó ‚],έë#œ½­˜} ¶8”ß‘$3‘2î% ²hÏ«ÎXÚ†/õ°›,ñèn÷JX ÕGû7„~o©yÈâµËŽìøò‹ª‹'Î>н,é·SS¢²Øç¯f šDœz†üäzêÙÆ´Ûñv³µšpç‹ ÓÑ'‘WßÈMû¼úÁô 7÷·ÒŽê†…ŒÚš.Ù_•bÝN ¯“÷oœ%æã½;HTªí ¤vUZT«‰™ˆæOtfµd­áÒòÔ2Ð`d—±Ç’+vLê‚N½KˆðÆä{ıhWl«¢}*Œýƒo(¤/÷Eæ7Hˆ»ÔÒuìÎ dÝ2$¦ ¹Þöºî¼§»•ðµÿŠ"#j¢æÔnÚ!‹ZF© »ÌGìùÖ9ÔxJ¶½ÑˆEQ¢~æô EÝUÏ­Ÿõ¸bl¿«±_ΙÏéd2þ¤4#îc#©‡K<ˆÈûn]ÊèY-´µ¬OK¼§˜hD"©Þ|a"ùnÆ<¯±_axE\R S\ùqÿ­â̆5]I‹ÏïNGE<¼0¢§mzè•Þ×1´;{&Þþº ÅaXoèGéc »,îÁo‡ÂJh†rs=|9:í_“GY½L$šŸ³ts'¿ý ö%¾u_W"XÆ`‘ÊH-’Eó õxŇ?¶ÂÈ(àrÂuÒUh\ºÒlå Ê_/Ÿ»çGNE‘Û{‘l }‰×ÖmÓ«fmÃë¡jgììv‘A³5½’VòcZ¤$<†¶S‰ïÉèà›ªJ~ ïJ°näÉÍ(ÓÔñžÛ[—â´Ms¼»ID0hZªg´äo§Å‘%AŠ.aO ±øïäC¾w’؅ܶÙ5‘&¤¬ðKÄQ6=k—Üx.ÖØ™Ç†:¦›÷—ÌorTÅœ%åÁfÄøÉe-ÂBœ±éKŒÏ7ƒ)»ÁוÞ8ÊÏôžÑàç(÷Öô'°ñ?àz0ÚM6$Ëe­'LNhc0ò~{ÑÝ·ÕoºMj]Föš,•¦yG$ˆ/4¬Áz{ì(+7Ôð2 \Ž´|^ùàq… Q&oV›ˆ²%šÌb“y±Z3M7&´¶ÿ¸­#KÏiLŸRá ¦›â]K~ü.ªíüÊŠ†µ}3jŒÂuMØ3ÅrV5y<ú­}[˜ Ðú?íØ endstream endobj 839 0 obj << /Length1 2390 /Length2 20733 /Length3 0 /Length 22120 /Filter /FlateDecode >> stream xÚŒ÷tœm× ÇIc§Q3±mÛV“¶±'¶4¶Ùضm4hØØ¶oîûAïçýÿµ¾oÍZ3×±}ìsïóZCN¬¤J/ldc`,acíHÏÌÀÄ•W“ff01±201±À““«-ÿ#‡'ÿllï´±æù‡…¨½±¾#H&¦ï2”·±È8Y˜YÌ<ÌœUlç%qßvíöÕþ”ç/†5a0@¿š.ÛÆóiC’ü4ƒØt\r²ã—3K"K”‡¾ô”Uš ЗNÕR¨£é<¸PÎ^>¥Ääí—dÃAÅDÇeúJE6q8§éŒG£áy¬õöÛºòƒ™æ›:/^À>§æÐ/voXùT÷}©A„.µM”Ä[óÂDA_œþgÂÍ4ø99³ŠÊÂgiGl/TBãiØmLŠÎ}:a¥Æ•Û‹7>€/·üæöÔþ¨ j˜²+‰!_DüÒº·‚YE9Ó¹ÞR°XÅîmp”ÝÙå’5"o,ãåfCvq†sr¢Wš‘f'’â§ÂªMN†å8"Bɉ‚2ÍœmUQyeÍ]ö’7ôÒë½JŠÍõK•,©Òb4›¶¶×žw­ã&Ïâ˜{ÅN =fíô# uÝ•L}ÞÔ®l,ÉûR,pASÇ6‘1f¦ÇcНlš–¿¯먰‘4ÌMÒBZ.FsI6TÚž¾å榕(æVËGõp#‰ÉTv¹a¼œ.fãÑÍ'·¦å5rp°óD ªú¢Ú“²4Ý‚ÿ€E{­}Ú90êŒ]T±~¼Øßóö™_Q‡Ë{|bg3°|õÀLí˾ÏKxÝÕÂk¾¸-ðFû°Øb“I¾_ZDíǠÇ7}”õ>«cª`ù™çò(P aå‰*ó‰hÚœŒ!æ1CtgDà׃‘ýZ÷—÷^Ö„Ÿbx:$DTÏ«¥nq%‚¥UËOe`Ab+Ù>±ÀÊ<<̾Øä}.Hi:öZêWZ“¦|S7[i‚|þDÐæ nMl{–çl늰´“¢Ìƒ`yºENê‚«]Vœ´Œd)T哯?Á ~kÃKsè&²ÉEüÖú,æxõ|¨¿#Kè;á“Ìãõµƒ›Qþ·¶ÉiŒæoK“«<ú'‰ ÏE@ß‚0óÕÇ åÁD”jF–7.€*ÖaÚn[É£NòŒÑgD¸oú#hù2îuÍR LÑN™;X¾5SªMË6Œ_ô`)M©Ù1GKy´ªýÍP²¾$ØKv'¶¸¸kæìûÌÀ 3êõLÝK+×mp'SÈ„B´¹r˳TöÅo”nê/5ÌêûÁv¸kK bI/æt¹/×ìÉMx’ˆŠW»x‰ìe tV2U²RØ^;gSæq’Mq鸡µõvw´ûQçÏ“¬_G‡äæO¤‹ûå#×Y‡Àa·¶çbr² ÛÇh¬# =¶×¶ßzTFŒê1v‡_ ÛçpÚ*Ôü·{ŽûKÈt¼|Dä_×tcd,Œ$§`(˜×&>EY9DäÔ*䣫\¿ÍK²8`㈬αÒìàÆÄ•éE‰~:$É6;‹ùU\5h•ûó«°âŒ`= Yžˆ:æn“Q®…™HdüÏÁ8ÆéÒNâ˜6‚ø¦3ì©=Ü¥±ÑõÈľ7S’_ìûüÉæsöçY×r;ݘ\ñf<Çæ„Àb»†Á\ g–§U½(ž–žhh±ˆ%uŒe+i¼”©T,JÚ|6­ïgjfà-µúE_}7xò7#2(=égüݾcͳƒo‰%£=‹‡Nþ¬e]JF.(Ì%H|ègÊeO´&j-ñu®ˆ¦!6 Á€¿Ø6Ò²@Œ{oœOvÙPóÊð¶¤M‡lȰ4ýrÓf`~„Û£4ΠdÚßÓ*>B—ïpä!ˆö3í^< µò?²O`Ç®-¡ÁttÔ”ÅwR”#ʆžG=ö+.™eß…ŠW²BÍì7 5¶ÜyëúVaÀ=Ú¼ö¨ RbØGÎ$‹·q>İÝubÀÕ¯–›*êF§„åtÊENß9˜ÎŒþ³±íFÇ_VMzÙ½¥8ë÷ŽÉãf­Ã>6XeIªÐE’‚eÔ WŒO3åvJjâ¾ ÒyvÆÿ A@3™-èê#þÀ,Å&‰£¶s§:ëÕˆ]NKoŒ±ÅÆ×8ƒO,>-VRæ¡Ì^v¯meºJ,Øž«ú\'#Þ!cãµJ›wl6…ºÇûÁ¨'[üü»hX‘®S œÓgcƒ¯#Q¯ËFÖ—r=¨³kÑA>B虦>¼1†á·Ý|õçymfžD5h‚@+ä~Åñ“Ð †œïª`º7ÜoÚ±ÎUY è–¾ ±­wª Ž»³ÛÇשÙ]½ßÃÞ‘”3e>sDmæ§ Ø8¾°S°\^çb·7}Õ˜${ë’WæQšlïÖ:ëžp)¼kc¼v2oæŸxßЕK *¸/uéSøÕ è%±b¤É ×;væ>´w>AÞª/_lØ—ís̘{Fpi`ðÉG–+=Ån­ÌÄMÙ?*µGŠÞúSeÁ†1,ˆÒ%r®\‡F#7A¿¶¸ #$Ô¦ñò9l“91ÅòŒ—ºžÂã +€v±þû}§é[^zÂë{àQ'q­i=’/¥IŸ ]K[¨ãB†lî×¹gÇû[ èiˆl:>R°Wê­/)tî)îáS]‘а{…UäÌĉù`CÙÕuA$¶N“/€«}{æâõmû——j !Ñ`*Ì&$ÇÆÍw¦Â ðŸ²Žèçs](¦"uÏ$sëE÷çb&Äëüžáq%Ê ðÛì[ëMEŽscÊvã•§¿SIZNÜmžyäg~ð,Ri}„x•GE8ÀÔÆt6; D¡bÏqãà:æâ²9Ba{ÈG®. ÍQUFv ONÈ^o›ƒØn‰ýláÀoél°6™Á5âY;ܧաKîqñ«¸N€‚Â@+ã¶Yãés‡êP]8òüsí*ØLÙ°˜Wbû­äíËA¦1¿‰œ'Ê €ö”zÃ5vZõôÉåÜmÊ7Mg[ÄIIW ‹t«jtŸ¾\€1æc®H]KM™„Ækûè¢#’|ߟg¡åŸú…΢Ö;Þ<¼'Z¥Øò-¨n£ræéê˜é#0ß…ÐF‹Û Ndç\‘5„N$×&ë÷”­»B>·&×c£Ýµ¦à*×W{€‚yó¡ÑfÔåª!Ì‚gðŠæ…öÔŸGÆŠ= þIü‚ÛÄ鋜ð*o`:ÞOo°gíÏÆÊÊrœÇç¿Û®D¶Ë`9ÚS(±qóR}'Ï>Âä‡'ÍlŽl†h=‚šâþ›ÕÎ6'©}–43Ùƒ‘Ç*6¡Ÿ¸#«^¤Q,õ½K—ëµßgB9¼%ôãÔö‰sa„{ìdF ª–vè¬ïñ£ÚórNqK=÷w·°n5ú¤±5Qg8'Õ½;*nu{ UÎ)‡õ® VÄˤs¥Îå'Þ¡—jq6Æ}6­gWö×>­z´‡6_mz?€Iz±º“õM.ņפ‰«=­)¸¿LÕù9,ý%Ä”L`ÅÕ_øøAä»»j8ðh%ù»Ûm´ºâ‡¯ýÙ’‚™VÓårCgïû —0–JVU~h0çË¥¶BÖtn>½lóØ?ŠÀGy\Ò2qd5õYHŸàᢠ]¨_©œÁµõÛã [ÈmƒKAtkÖ×nÚ&Rº¯:¼ ÈnRêqÐŒ«¤$ÔŸæÞ›aÎJÆ|Kº‰'Ó.¡®?p =|ŽÝDoVE <ç:?V  6µ¥òÖl'rbXôÄ'äïd¾Ë«2_u¤ìÈès7¸¯jt;ä%L‰UCÃiJ=¡gh-gÆ™wúP³º®[¿RZÀ:±|d‹žª¬T0µV¥ÙmXŠÞìS¦B_–Ùwiñ¦{¹_·ššâ™Fêë ,¸„_B«F¿ßUÓ!Û% ôƯ@ˆ‡¶²)ˆ”:Á]uo»9¢L¹kÛ–· %D%1öŽÇMWÍ2®X®|³\¥ÈØÇÄCUñŽÖp!뉻¶Ö䢕fwù¢-匱RÛÁ«N2”Bt°¡€û±g½å‚í*=hr•f¦ÿ–ßãkæ‰:G´ ­ùÏUþ×êÀж:ç‘4'¯2;‡jÿîb:å­j‰*A•NI+ý 讇àÞîA7D·—cƒ×)u¹˜h 4åû|!” õzŽJãåÃß-­´ÒØuƒ‰ŽÄ&¸.ƒgMV ãí¾r›7Û-¯_ç¾LË-+^æß»É”+ÇSt+C²€‘ñiµ›QŠ~PüT 5…‹œqFô^‡-lý f:ˆ§;6špžo‘hŠa½gm÷é8:¤ ÞL„ã¼NǼåp‰À5bFÀ@пVºìW.|}Ê0zCUHÏ·T/D°*'uÝèqÃâþ¾ \RrjX©žkÞrž£sQ+©TÜÆV±¶ò\ü^«øwäIªgèY1þ¥\¿:Ó`;?|Ð¥fŽ$: û—İD/Öæ!€D‡ñÓÛ‰kC &«¾¢s s$$È~•7ÃO²¿—´Õü1›}·­ËÛ†·ãDˆÃè¨KÑ…Ð^[©µíŸœ)ñÞù1=þͤÔß@[ÀSïý… m|DÂa_ò¾Qli6ÓcÇ}*»Ï6zŸç‡gÚÆPÏ6¢ƒh%ün«Ë\ñVÏ`Ë–ðjÐ<,à’Uc¯[êYàæM<Ùà» òˆµ‡^[ƒš øÀªÏ•%ÔØï?&CD°Î뎆Dº~ñåÀ¾X´==Åbʧ}Zæs:¤Nl9²Dðj7'J3kOë{ob£äáÒCÔWþÔšˆ!ÛÍa‹j.wÙþŒ¿þËÁµzi,Mï$!$牅_Õž:‘"o°Ü›ù\ŒÌ•”}Þp(íw§ýÆœ™‚vÔm«Ñ‚ùÂ?qÞVnãf5£>Azïñˆ´dŠ·Ýk #¿çû‹7•ÞÇIÌí'G2.µ3¶pÚi¶8õ!d}š øÚœØÝqÐå*5mAè`B•šª#¯+LY}§(FºÞB!ÇCú"â†Öóð=@¿RT•Áãë¨òÞ”ïøáºà{Êñ·×$K*¬Íœõ±oxu9ú‘ßÕÛB‹Ïkž¾» mE¤ãYR{êo¬–bK—~’Í!õ~+¿O¶«ßñ‚= fÕMÀ¢I“ʪž•´š| §šÀ‚"èÈZÚõœõÏ•z£´hd7WÄgöPaºC¢O³-× þ2Ù Æ:ó¢ÂŸhÅÊ—­Ç9/—bO¤Ð…„ù=ÆK1¦ }¢Û /îGMß®êÌ*º_bgÕ%ŠXöõšõÍO+©sr0©‚‘ÌÒä “;ƾ:ªè•E-)eû“&zı·¦G¤‡mk»î«®(RÑE!Ÿ¬%EH}9‰“oY{—BÂpssìƒËz«dÅÉVäMŽôùŠ07=X9 _uÌ›(ð˜WÅÜìB ‹´D4¿L"z$,Š£ˆŸþœäÈhUùt)Ìü1 9©¸ñs©ˆ `JQ“Hé!³Í×”ÉgJ÷ËÈ×Ã8ã5Qn½u¦f liެRHåLÓr”Žú#¶½•¼h0ˆN»34ÉùúúܳP`‰$âËyÖµ·^)Ñ„b¶f²Ò0¸.iüÂ$Fýçt=¿ÓúÞÏ&‰‘Øò5’ØkTD9y03(Çù$’UýÒïg›žl'jQ³"¢Uæé¾³* º¾ôÌÚÜNeŸ´i§¸ ³ÒÕì*é8 ›‹éÁå` ß~B5bÌ‹C½¨\{†QËc=®XÛ*¢2‘öaJ4Ð4稇ңÙLB‘jÀÒG®8ï>‘ ¦æÌ8•¨œD[E»%Rœ˜×Bâ՚Ǔgh°cr“›Ó…cËñ ΓaJé`Az¶êZ$Dßà€½T³°ÊŒWÛTmÀk*ZŒ£›'›ÈŒ©fÅï‚,6# ˜;¨Ù $𸊿w.XðË)ð ‰X<ÇËï¼ ÁÊ Ô‡fÇÉ[Ÿ¦ò`8Ÿ¢k¹?D”«9<8}³­çlës’¦ºnkbõ×Nñ¾‹BCwÄÚôÄFÅð«„´ð6²? ßM$t×!Òû£¦-+â=ùQRÕ¶¢ï?:¢é6ô7*à¥ØµPB£¢¯ƒ“#°9}eýˆ©nnÉÿ•íJŠg'0º\€d?£r–EK wS¨ù- èLãg«úLo\]ŸµUz,b(k/Aw"ò=ôv•‰Ø’§×¥u qÏôà{B9Ï­KÌĤ9ÏŠ¦5úÂÎÇçà~H‚=NZZ,hT@ÁvS®É«W«“Cƒˆ§]C§Øöû å·opžÁ2㡤n๺ÜFj5;ˆÝþ©Ӊ½ s@YY Ú®·X’ºá/ Zb¬öøEå"LÞ+IJ¤ áD|í¹¾‹ùB®KtÐ7ë° ¤°IcÈ£€^˵Ô!C‚ØÇÓíFߦg“Ïë«“´Tjb+ÁOjø"KÉ)½“é«ß‚C-/è«à^—ëí`]J¼¶së·uç\éýŸ:Jnjm¬¸4òܲND§øOw «ûËÛT¨Ž’÷·+x]5°k€øJäSy‰-ä=äöòÒ#œ |¯F†“-nˆ=iT͋ܘçmª¾Åý¾¿ñ–~™„Æc¸¾yº(¥‡ÿ÷ëw„@N®{@ì­ºêÍ™UMëîEzÝ0åG¥‹îá Ô«ºšéôÓB`t=>®çr¦æ*ó!üÚð¿Lu'º>Ú‘ïêåb\ÓYÓ†ë¸,ÇÜ£¥ÑË:ïKESh¬øâtCÍß$0†Gì¨h¦1êÖX²ëfÑ»;~1&^5Eûþ]CŽ” 93$dc%K“•o&-,@Š÷gÏÙáíS"÷7åöð ‘Œ.bs‹p¯è„å%½âipÞúyJ‘¯U î‚ÃÌÑØùËbà §†)E¾5ü0ý =¬ yµíùCèH„S–läfö[9¡ürO®t ­‡ò~ +ü”$Ó}ÛEfÇòù;ñ•¶ÐõîûYŽùвf‘ [‘Ø#KîüO¤!SÐóÖ* ·„âs¾ÔBPXd) ‚\Rìå0áTâú0ž=ÎþãQC— Z‹&WgŸÒ‰U·råZGíÇÑ8¿{ âAÁÌ\מ~ÙWò¾)÷,½Î¥Aw(‚\Û¥‚1d“ò‘¶àVßV!¾[Þ09ý†PwYÚ-ô5æ â}U¿`BóEňu2õ9JŸàó`‘˜QÁ~?= YM%ËF¼YXÕf¹~òv{¸µuDµ~•ƒÛì]$ûöÔÓ–K—Ñó±1D—%·ïña•ZÅ@†fYX—¸Ã±¥ËŒ‚ÜðôN¦s~',Ù娛VešAŽÎ£˜Ø -u¶š%,Vm[¿HÝ”ìð©Ô¯´ˆž!bÑu‰ …æn*ÇÏ;ĹÜÎP4r94QÌ¡¶Û>Wû)ú²Æj½Çâ ~_á7ˆUÞç”»ø%Ö”Aú„]Ü4Ü ˆ[|::ÎÒÔmy^Aò|ˇ›ÀýfÍ¢Úµ)L‚áxËãXÉcôEá:C×íJ±¤S–1.Ü?ŒaɃí\!ÁlÒPäÙåsQ´a®û‘˾ÁL¦' 6·Ócð”E÷5Cm›Ÿ—o×UÿèãÌ48LFí—à6ÖX$ã$vB–zGm#ÿIóqÎÀ€RQCeŸÖN2¹st8 *ˬÎ'dÑh0Ñëf¯îds„J8‚AbÀ;Qvºp‰a”űoî ‹òÎÃäe!ö‡áôçU,%¡ jf²Bo¦Eu‰«¥<¦hªb?2ä”úìŒ|óÔdtXÒ,XäsKPB‡ýdù;PÔÃÞô´êe)NLƒ47Ƴ6»³œ 1µFç Ñëá*‰Sù*?MêR5r䊟îã ʺR[YrT¡ÕýœE‹«Êf³³Öü`öùö¾÷M«0Xqë4(0Vµ¯ÇØIxefçŒM'A+Z¸ÔÌ#.Œ\„9%Ž"U‘l1Ž"\jù¥Ö$øyød¼˜ôœ.§sß"~<Ë~ú¢l°O˜ òÉ…/©³=!íáÐÖ߆iö¾ìÄ~¶fÓMCëÕ•öºkÉZÌùÕ¼r›µX|ÈË‹-jÈ*¨Áìa~6;J¬y€WU”Šõ{Š5êÛè}- ©´Ðk | å~ÞÊÊÍd³ìÍòî2}ÿˆÆ¢yºtá:Þ~/“lsš-Ò¿å‡GÓ}>rœ¿äXqF!.+½Qà¦Ñ|4ô#®w(Ð=Á"/‰ ÷€Ñ߯MÚv&œ°¥!Nïd< FmOCc{9Sôò®0îââ(LâÅ&š›á“BÒÉΊñ/˜Íi‰¾a¶ mtð&ù:7‡i­—4]<}fÆôÁôj1I\©6Ø*Óf˜2†“nj©:ß^Ÿž|óЇœ¤{d…Ô'†ÉýL¹½¥àn«“´‘5yƒÌeŠÆÓ*¼K)K¿Ðæ´r*ED %#>Mß>ŠGzhM²ân÷•WëÔ¡zÜrØS÷„ÿ~‚e;sr¸+&$3#¨ûˆ)NlIAeŽùÃo…T>|M í;î`¹¸÷q/9ßy-ɲaÿºêªæŽiJ7ý†‹ªtÍ®„æ] sz³ñº Ôr¬ l2:ïÙâ0:‚“y›³s ðIÉm„¤QŽº> jv–¢ŠË»ÕƒŠ‡Ú×Þù"‹¦¬^\]ô}4žÜ_Œ²ô}“’÷G^ãøÚ»ò»$õAG>/Ø{ci1“ŸŸcíÍ]"Á|v ·ú÷ôƒ0VBí&>NqDÞs'`Øç³Òã : ÉÖì¶ [Lö—Ä iHÏk÷× Qþæu’ëÔÓæ6Ô¥df"ܯ»ÌA¾„Õ¨‘*W ÐyÕ=«læ–q¡¡Y?Ͱ/ ¶X?ÙÔ€½wÖ7Ú>¦¯Þ-5à†æð+…>ˆ‚ ,ôz܃þìÊüAmÑsÐçHP+úú¥«75õj„£Yˆ4®Ïúì3V^«ÛÝ%¯Bò7äeÍåèà›:I´xX}L8Ë%°0kUÀ5ÝyùWä QeyÇüÈ6gÄZfÎJ ÍÕÚê½jÏ#™m½ôZcÕ¸uŒ0>}’ºúœ6߫ʎCDß¶šmã¢ðr ˆáwˆË3n&N²©îþ¯¬ßçŒX4.l'ê\9ëQc+Ñr!Xcê}*ôÜÉŽÕ»¾™~l4ki0+®;)Ò†š´"œîNë4U€sÿˆ›Îöâ½Þ]P8Å=«°ûÉÞ+F¦ðk§O=ÚÁ—Ãc.匶ädù±žUXÈiéÛœí³ }•lU®‰øµ RUH  ì,×À f[©¯Zª©‰mÑ„†âë^± ’´UèíÞ*yª9ó‰î£TÁÖßhÂI±( ¸èƒ ª§er‹S.ëõæC##(e¥½îŒbù"vãºpcþ¥C1Þ…!Ul Æ6ãÐåøË*+ÒpqYr©eõÎjP—1C|4³ß%e –>ÇÀõ°ZîiÂ{bš$ÝOQgvø]5œ¦CåÒûz\Çdi=@ªzcìÊ“éÆ²™àñ©n¿6äÜ„uÕ<¹%b)ÆýÆ·ß9'Ö–H¹Ë&ê¾W ?³ÌÎmIšÀ>Û`4+^Nûv»6êͯ+¡‡ ƒpj+ §ØþàK\Ä+1„p‚iÏ9ç¾Ø±°µ ö1_ÌÛvÄ\þ©éô†§Ÿ°ÛiÉðv?PÌ_‡Ì03"gGýypm+ìa‹´õöóÌÉb_4Cã\~qË’¶w*幸Šái8ðŒ §('¸¨£¶Ë¦¢«PTÄbx¾ÞET¼]¢/î ñ7#€…pžF[ñæY…¯ÕLi á1Zß àÝ.Orz&Ö…}‚…TNÔä‰]é¨8årñ±¦ÿl"\³Œ ˜Àë 4H›ÚÚîºyA’Ò7ä¬@+9ºN†6G{ñXå2dìQ„…_O°ù2¦}}6ô踫ʳ[W\+™t¯ZÄcèîqQFßà,ýŒ¶väu¬•íQⲖˆž¨¶ÆSe›ŒµÃæ±j \G?$ÝHˆå!¥^G›ì51¿Û¤wÃ%iš©éi1h÷äšÇùÔšÍ Â<ÐæÑE=aÒ¡ëä"á¸ñþj¨æoñ³Ø©§Ò Çi¹ˆ3E Úë'º>nùpÅPýSzêÃ’¹7£gTs 2[É„ÒÄ g†„ÞŒ´™Á@sƒÔ=u’¶J”q‰û6|·›Í¯oØDÆk¬rJqЦ&jYæÅE{ºêdY!­¥8=‹¥ãp¤îW‹42Ï¢¢†¢<úpž6î\“Qm&“å!"w|yùâ«]¡@OR½N.ˆ6Ѫ™T€7Yº,½žqÁÌûtùsã¾Q"Ñ-æ¦Ö˜*‘޲@!ä«e®ç¡ ´Š2y)'§_!±5—´@Mâ·å=ÝD•Nh¸>*l yó¨ð˜ãè†ã¾•Ÿª>3ªh޼€1Úk„Á…Ç(œ Ï1èªêâ¦ÙšðÓähÈ ¢0–Œ¶ ÓÒ*&ÈrJ¡¼qÌ~R¬i³%®m¹…Æ"ÕIU7{lå¤v9ÞóÝ—z«é«`Ç §¼-å¸P°'ªrobQõ$hp©Dò; õcÜðw–Üsse\©adÙ}`žÇÓd|áš5#<¿ƒí›s)óp*×$ƒv”ØRM¢*Q½z¼È«²b3Óêì÷•H²Íž­Ôž°½Þlê=ºõÉøÙb{.±r5%Fþ­Ë¡cˆ~óë ¤;Ò¸þ|û>ŸÐcaô­þ~c¢ TOúpuH[Xƙ᫓üj.í쪴¶Á¼+èÅÕKÃ*0„G?+EÒ“¬Î,3ôîÙ¾Ž/ÔÕÀWô@ºØM²éÿæ6Q:õå> B¨“µ÷¼sÄÃ4w{F÷I®ˆ£ãBU0õz×ú^Nì0蓲ÊÍØî¹:40òB»â‚Šâ Ôôí«—¿Àɯ¼åÈ£\¿, ‹šÔ/o<˜ßf·r&¯‚Ù§i6lgõ½¢^/Û—½ö<îˆ#_˜‹d…Ž·.óî#Á¿7)ÎûåÆb®X"¹°è[!#ºMå·±wI‹W*]©H\v2û'„üöüøŠõ”‘(vv¥äV2p‰öÜ•¶m³M1Ä •E»“’óÌ–Cë²}F !ö½RëøîÓ3 {®#ÄRuŸh} šAf®¡0ÄM06›÷ÃȽGÁ™|ñ½ $Ÿ‘œ}½õ±SQnµÅ™+xÏŸ^ÀÖ³{œŒ¾Ó5Ûo¸ø9Æ¡GãÍŒeX¤xÜ Áö‘›Å/ì\òÉð'ß%À¡¯|trQP ùÞÈœürÝEq•~qðT3aˆÀÔÏN‰k…Ñ O"ªô&½¿eFòr<õƒ0efýçT¹Üª5/Ê *dT[$Kv혊ù㯟r7ⶈ´ ²4sÎ š“ÉE|æòiíÊ_0SÞN‰‚4Kø¤ì”aà¡7ž¿!ì«>ÍÌg”~Š­uÐñ0‰›½&¤`Ï+zÖÊ´pì=‰g~Í ‚²sÄ]+™ÇâPOìøz0_Ê5Ò³µxµ²SE4|„´º¢Åçk„éUš4­ó]„¯Ò²UŒ×‰ì£ãü¦*ÝÜÄñúà‹8tD*y´*ñ]÷aª„sD>TCwí©Ô)n”Úô^ê DŒ$8;Y‚:ˆêp“Þ‡¯lÊþƒXèè e¹Ï*³QFûL<5}y¼.Oyl•µwª’—^3 VÚêì½¶~d|©-žqUsO}Þ^í"6‰0©Ì÷=UÃ*”Zh÷Zm–¿n—4‹rúƒ+Ùù`Åt´ò—VT§¬w5’ÀÏ„VÄÚÞ©{­;[ΘGw±˜a[R¶2~³@Êð!j x³AZJ½L{2w÷ŸÌÅ­÷ E[2ìªÃä­¶û+ÁÑ¿i°·“ ¥ÉĸŸk9 oær`›BSnǨqqdý ø’oþ¶¿€nŠY&¯®#ȺCÙÞì4,îu™lšt©öauf´‰âò“ÌlHù‡Ø]h±Ô_ñð6¾Ý÷Nz¸KÝŽ$OÿT—ÿãªÍhæNÌ@xDÐâ5ÿÿ\*šdz!Àî+fPkÒñ)ý‡Lź›å’Ër‘sÍIZêãoàG3?I!MôøD2.9æ ËÓȸ“êL&†\ÑL-b8,DŒzëXΈŒ3WÐ)Ò3Mԩ8ž7¢³¬öPYîWö^·w²öx0-w:zÆ!]é0ãÁwGØ.y>3f–{6¦Ü„ÚfçTeA­º’èÇ) ž-!JËŠ Ü"(RwQ-¶ãu?Û«NWÇvÚ›¥l½ìúvö9•1ž¯>Ý/¦¡;ô¯G=s¢™Ác‡—¼’ôq õ^½M¨9Fñûf½?LeýMßa;Í1‘Yв5C6¡Îõ‰ƒ‘ý<çñ¶¼Ês+{ß9÷´ô”SÚ|¼jÔé£bæÉK~¯®¡pˆ„ “îÜ3ìCVul„nz46q~+[–$¯/Ý¢Iþdpš3ê/ D§78˜€ƒ­!Í„á‹]”‹ò”¡Ï³ŸPœŽ¿§&X2eK„ÝÓ¶³·Q6‚ ¨^·œH ¢'¹Õkœì_Íèè-ñ—„æ‡+…hØ]ÛˆüÐìbÌDéPÉ•oh%7ò¢¬ÿŽóz‚QþÕ4 øÅÝFÝ ­ÐïÒ^#…#S×Á¥³Tšò[î\,øn‰õ[x ÚúƉ#îÃh¥eÀœLéÞü{«><´ 7¿€þcpm†íl×±Š`àÚ6;A]Œhb$âÝB j©xõ]¶fcËܧ à çõq§z;2ïÖðY™Ë¢£<7‹5mîW éå”ó$F'@þ¸£ëòH'–ÖÈ».ŽW#d/ªuÏíJŒ .%¿}²Ÿ}œ£î©¥ûÀ¾k£¹n±ÎU?íMÍ×Ö­M¿ŽŒü_ÖäÖ`Y¿DoH/OºßfªÆ6•jÀŸœºûèmmyf»Íi–•x…·}Àät‹òÑ+â^·.¾âÒ–ßÆ£¯Ÿa Ÿ2KCèTsƒgâ팉¾üœ ãƒwM/Æü6I“,ÓCá&ÂUdzÁHÍøTe/ôÛN=sž*Œšl_Íöiº Âþã@Š\m¤ÌM®"…ÇôÖùPüìr¤×ïÍ£&xYM\Ù‰JüèUÒ,}càËb©{¤ìñü À⬌Ÿ"ŸÇ6êÇÒ–»Žn(ap·<È:¹É8^gÔÉU•V>­±§à/ë C*Ñá判äîÀdL°Ãˆö'ŒÁÍëEÃÈwûy¡;¹ Š'õa¸C…-²á}$3rÈÁ%ïY®bçÌ—¨è IÒIój€C@C`›Ý¦7¬åAc³~)'²"P—FÕãy±Ã´óæê¹3g@ÒÏË&@JÏ€>® V¸¢Â‚è6Y¼Ò²û„cáFþ Š—²DUyZ¡5ë{­J"6eïÞOe%¡ûçê:"›2Â{×ÞÀ úŒ©êÍÉZø 7VÁ/”h'1ÙÖæGüQèº^ˆ«c—ªPƒ½¯²B ”M!V¯¿ãJ{RøïÑÏbÇ*á „ÝN©*÷VítUiõ!ÆÐ˜~¥^œ ?ÒÆõ&k_›šIæ9i%Üåa…P"ë:kÛAM´?|*œsì,QæJ6àßúúþÓÐ{îf›-Þ1š3ÿYRED%ŸñlGûä¦U³‘á’?鉌R^9èݽ ŒuÓ”®žéc˜÷.UX;г…i<]¬ß~-4B‹@Ùný”ë8^z§ÞÕ©TîJuK‡[I XƒÕ>¨ºö7 ^*öXCGœz˜,|0¦wså}4cóÓFN¶uð²:È_G.ä‘[fZöA°eŸ«JJެ+"¹KtúaÄ_ØGë¿{;Il¸×d¿|Û±²Ñ°'WŒÕŒýÐwõ‡†¡÷ô–/±†D•Yí÷Š ŸÜ¥' 뛌ònZ°E¼1|˜VNYØ-µ§í}’"ÂÁ6nÌE0ôvþ´nö+“Ê`á|vÀkƔա@C¬ ³¹å+“pHò%¶ÅAÂÜi$vXÔG"ñ.)­ÜÞÅØž Õ=P¬K©±-åbê2fÂkÿ¢ƒ c^I;=iÁP²Fn`âZÞì!ä±hHsà‘.¬Ô*¹qŒ#•c²©E jãH~Þ -…Y‘óˆ‚PƘm˜†°‹l5%­§†“oQŽe^q†‚bp--š³ÿqäÎúJ?f¶³û>?²Ýƒ¨ZÜ®xÌuìW{ìïkVÊ~öB‡­áÇA€s­ÄTnÛG  T«y¸kHu%9šÔAõìòÆhtG;Yz¨åët «îë21Û,%JÌ&a«ŒÑ嬣…œ§*(ÐÍSB¸~XïÀZ‹æ@"ó.ìªùóQàÒœIãv?ÚÕÓû™Ì ö;>nPPôæE`8p†’-À÷ß󨪂ê§t$¤CœóŠƒôË…‡¢4 Ì€Bø8ë”ÔÁ§T²ù"€ÂФSo"'œÅ€:dzÎVTýÛm¸I/ž¶òÁæ(k瞆ž=r6ÞÆ¢g.“Ü* ñ¿3µoº6 7) ÁÐ6Ä!^°=xB×rШͩ""¹Ù.ì–Ø¸6r¼¸d0µ1ï0&6õEAl¸«å½èN^ÇA謿4Û‚NîÃ#Q´{f b¡bÕFQ¶êY°æi§$šYñ„wòï›fžCê_Øä(ÔÔ>æÈ„¹Iü?MoZkÁ;[1ûòú†Âvª©í^Lƒ5ü¾Örq¸±Õj6˜òä¢kŠÅÚ L7k(¹=R^œÐ°«µí-xüЃ]WT hVÈTTFÑ«—åj8Ë5A«qgšEbDܬLƒ×4­@8¶àÛ.[’0^K{Ú¢å—@4 §‰bJŒƒidD¥Å@™´hï6áQJ²z„ùš+›Ÿ`n3…ý¯uAþ®xáÏÜ}êcအ&€›ɇÈxÒò˜J^Íþ%?x'ŽP0¾±[ªÐäêYáü1‘!èÆ{2ï<ꯓ¶¯ªŠO܃ÁŠÕfûG[}äÄÀÅ6u¦H M£'áC–LÒà¼S^ì3VªbÜZK¨£ÃZóm¹-ŠøøÒiÉ_1…]ÙJßæqBæŠtŠ(â”îÉ|¦ó­ÔW„ùî­o¶†T"·PÂOR¬§±kdfªnK.|2Öì¹eçüUj™ZÉ›"=0®ï.«’Ôh-L’WÍ® Á£/ÎæZ†¯èe„_©{J/Áóƒ`—OÅÄ\DÏ”2„ö9Ùðæâ? =Z¨8-ša\V£«]üqD^ªx°íJÜÙ+Õ†ñfec$ÛËgZ¦u£ðä¡wa7³oZô—TÝd`†:\̤ÛÈ眊0ùŸ¶Ã˜w.}˜ F!7;€‚~â•|ÿ¾ÙBKîR µdJXÕnzj€B£¼ª•óí,lCA!êXMŸ\wÊè;Ýóç?Ã¥ûX¦´ŸÈõ¨-›+A/«…˜+±Ý7fØÎpš xš \ü‡ùۦ륢Q=g}¾ô&bÑD4Ø·×E·éԼϥա®ô…E¾¿3<{:GÉf5£üÙË¿’Íÿx„v7pþºN‡Gèß¶¢áùìÏéAeÓO›l»Ÿ¡¾$zø»ZËv#ÎÆfñÕõ8ÂanÁ„W6e†Mn%-U Å<¸0É™£¸ÛÏ"-îyæ‰QØ Ðò÷®_P9r»sÍnòâMOy+fOzí5¾€šñ""ø6æl\_Îßì³ãÚvyXÊãúñã[OPW[” ÅH J±ìÒ’ð C ¯Ø¥c»–Ëø øOÅÞFY©„l°hM™¢`èË6xzÖ+¹oì>ì¹ —Þ‘j¾{hTøeÞÆ{°\ÊIh _på¨-£Û”Õkçl ®ÀÆ hHÝôÃÖâñ¡.¦'ƒz«fRK$»Ä°0”hc @¬ nÑ~p¨LÝ+íi³¤i_—®ÐA‘9¯Ë£*N+)Ñ4mÁùa â¡Ç(ŽFy®‰8±ßs²,,Üê ªˆ{ŸØeö¬ëîü>R ýI:œ!GÉZ;˜kJ¼Õ8áÐOQüÔM¤ºÈ#ƒßÎû¹Y„°›2-‘ y”HF½Í__¿\­î%×…õË3Í%t€Pôä\çŒ]]«Ì©±ÎÄï f؃Ïf©FÎ/Ŭ;u¼1Ü€ Et T:!ˆ€Ù…Ù.ËKËLîÍ™¾Y3]šCzY)Jú ‚æäªYî?4MíµCN«—¶S†d~eÔd¾+cÍÔ¸O¢@’ÕR˜ÀÚݯéUh½¼ìzƒéRLH™jß÷Gž•’›{º=âµzºå<‰Ü{½æÇ8¯05¬¸„jcØ=¯l-”ä‰!»±Ðè.<^kÈ$˜ ZÆö§Q»; uʲS˜)fÂh„k$mê{½'Ñ5Ö9{¬=Ú…ÑK"γšÍ¸ëûï„3-”.óqwS¹Í.s/C³Y‹A[\q[¼G`9ÿªUÇê¬ÏêQà}”±‡×*“­|1xó²‰"ܧ³z{·›U†«|”ÍV>Ä›Îc8óØÈ1°i­é?›áŽ ¾­MÇ’|ûǰé¿%ÕÔµÉtæÿ¡¶ Ö?“«Ò=¿ÔŠ ¶Æ3˜Vpm÷W¼ ¡n$W,)‘pô­:Fž-ù•c¡ŸghæõÏRØ9·=«a6¨Û}Âýùõnñ\-C»°MWëcëƒ õ{j°kÕÂÏý‡[ÏDÿÙá ¶~ð-–øËNÿ£?Ü0KÕ ·é­ó¶µÍ¥RýÏVIBÜðœã•ëI¦ùúÍð9§¡—+*=Èåûî“æÂkQ¡42k2Q\dzÊ€—7•::#¬&:ÕxÑ )Šñ6’îvakHù\¯ßWž&æ9–˜eT!Í6pE6Êì:~×a½rþrGí²4 ß}1¬œâ,µÖʿꄦ•"˜òwb³HÂû×É> ™í™ÙUÛqU}6ŠeÑ„®°åf݈ò¼ç¡o‘Üðc£y7|˜&^ÝÏGÃìÞãÔrûòóDÄØ!^+"v¼YõK:ú³#nî “¦_¨û‘bÚ$ˆNõ•ÖÍ­mæ`>Ÿ´rF1~q¢› ¡Í¾|!Ùí›Ãc#›ýlò‘c›TæVAƒvüÔ¦zÐŒ2Oz§Dˆ˜ ðÈ»Rº~/ÅìÌ©«´¤¾I„›ƒkî¡R‘!~ÃÃFL£èªÜÛMuç{’e¶ƒ‘¤ð¨jà†š=À6è5ë‰ëB%µÆô‚Üž”eÿé ý#Vœ"¢[SkÍ­>?è“ì £—ìÓ•Ù,¶É7Ù7wLr¼\J‚€_੼ààjár(O–=‡M æÍÕW“ *Bxn óÆ´6ŠªîI2KšÙd’}#AeU¤z¸ÿ8à×úN·[n¢\ÛIae[Ñ—_âïäÖó:Áƒïµ¾j &„p-¼û†e%ªî]-‘RÌ­{»ÇÁf0u懡PiØeKƒç9Ϫi»øÝ ƒ…?è§\š•_ôl»dKuÏS¾-%Ó›3FÂóõ†Ë¯› ßʧa"SAq„È">}î'ßÄ5{ï ¶-ɲÓò¦5Ö«•ªýsÛyÏغŠõQŒ Û©1€«ÌqhÍHõ£— …£”CÔ™° ‡rK¿ÝKUiJh Ÿ/<¯ÇraKéËšžBqI|(}ð>é?.Î ‘ò‡c¸| {`Ê ¤É”Ž€«-Au[â %c©²„xwÙ# BT{c5oSÈ¢ÄvφøP[Z³7.€›Ì+¶â®Æu¾níÖ·¤´(¾ßQžæ!¸Š ¾¤Qý¦ LŋӺ^¢‚ç6hž~[~“ðú9ø4fïƒã~â‡Ïguœ%i=4ßgm·5›^X ‰ Î5½¤Ñ;1q¿Rý÷ý25ÕGé½z Ê¼@ï5{` ¼[â ÓC[_¦nÔn‚ Š ¨+žDxjò¿"Þ ©ØJÔRÙ–§¾OýYLÝš‡‚:zh=Ør½I¬¥îlì Z¢‰Eļ~ªÙWß‹¦½oI(ŸuTÍçµÒçö!K:äõŠK÷¿\e„ä碓 Áéà-ÄnøDXHòÞëQ¼Í„ÏÌâôˆ~ƒœßô ìMPŒPhldnŠ÷ÏÚàa’ÆbXIÅI†'!94³Ñµp!¹Ñ½,;Cp(sv”¦kU ˜3ø–ž£h¨Z,aŠ/÷}C±pتsÏy´µ#ÙV…£†á³Âk½Í"r¿þŬ›{æzo‡’3ˆøwœ¯,lÞ¹ô h7^¦‰K']ó çÎAö¢l®A$þÃ(”ß ™è|§>cÒ ËR¦¡§‰øtèO*ýH%.áéž_²ûb° *d-ª/,šY”Éßbtl¼Ð%ן yš¶~×ҵݪ2¨d|õ]H-Þž·lY< hèÌ}˜Ð<ÓEÝ‘î3Èáªjj5[ â[k‘oä¼EL)"d]ú#Æô$û64ú Ý꒒胅ðH€üûM;N‡Ú.œI €Tå¶[’¦1qa2 œñÊR(0´ø‡>õì«×€@Ä;: ~ KÄ’»UQ…*1…]o¾qÿX¡xšôjÃ6: hŠNKÚ(è#7®}Ù¤å§nÓ ù)¶åYõ*=cF+r¼¸Fg¬gHTJ¦ÖzFwcÅÂe ‘aKÕ–´ÉÏðî*£¡š¢©™s?¢gàÓn)¬Eks_¯õ!™V½D§:GÏïÌV¾­u®™l—×[bÊÙŃ7܉çöoSÇe™×&°éà\çq;Q­yÎkÞß×sÝÇs|l³ÝJé;¤“˘J5ɾ]æÀÿ·´¥ÕN¤Ÿ,¿²¬t¼F¸uä9ØšQ£;âÓÇ÷LeÏ^Iq»é{>+ÿdÑ1ˆ~#qÂd: W‘éUÀ-[¬Q7H/ÿö—Œ•ÿ/8)$U‹0XU5½,!wlÚ¶éaŸhº4{›¦)à÷ï§Ü~¦5g¿»uþEY{û#x‚~J‚[—§Dòü—§ÊùNv¯k´¡bYÞ²¡ŸšŸ÷XR£6þ-ƒ6Âpc~G;MuWAŒ5^&A²çɹòr endstream endobj 841 0 obj << /Length1 1458 /Length2 6859 /Length3 0 /Length 7841 /Filter /FlateDecode >> stream xÚuT”k×6 %Ý%1tHÌЭtƒ”t 0À3ÀÐ%-ÝÒ „€ " Ò݈t)-ßèñ¼ç;ïÿ¯õÿkÖšyöÞ׎뾯ý +ã]¸DsçñÅrz* ~(À òã°²êAÝ ûqXŸBÜP8Lü!äÜ `w¤OìŽjÀaU'H‰ˆ~ Pìo ÜM ö„Ú4xªpÃ*wñqƒÚÙ»#ûüýà°æ€ÄÄD¸§dœ!nPk0  v·‡8#;Zƒºpk(ÄÝç_%8$íÝÝ]Äùø¼¼¼xÁÎ^¸›4'7À ênÐ nžÀ/ÊM°3ä5^V€ž=ñW@nëîvƒ'¨5†@¦xÀl ndw€®Š:@Ëû ¬þ€ðçp ^ÐÊýÉþU û ¶¶†;»€a>P˜Àêh)ªóº{»sÀ0›_@°ŽÌ{‚¡N`+$à÷è`€¢Œ6Œdø‡ÂÚ êâŽàE@~qäûUyÌ 09¸³3æŽÀù5Ÿ<Ô bÿÀ_1Ÿò]½‡(ÿ'(+ ÷øñxø…@(þ]ç?'ð7ûßÞ'`èŸé€ÿTTÙÂb‘@žÞßD<ÿ(ƒãÏÚpþÝAŽÔ3ÀñüMB@käèÿ{ ~§üß´ÿ«ÊÿSþÿ=‘¢‡“Óï8Ç_€ÿ#v†:ùüA õìáŽÜ 8rC`ÿ 5€üµÐ¨‡óGUÜÁÈ‘Ù!uÎä þå‡"¡Þ›'Pwkû¿´ô÷e {8Aa'pô×{™þW ¹zÖŽÈw ye¿Cäfý»¯Ìnókù…„`77°©3~!!€¹«6ïßðñÂàîÈ’cÀî†óëbE@>¥_®ß95Ÿýÿ2E|Nÿ˜HÍñ¹ücò#s}~›ÿÉÚÃÍ ¹µ¿µƒœ÷oû÷+ñ†XãÌMí%ÂjÃZ/jdxñl ó â÷GŸb¬+P{ni‡ÈI^žÆÌÊtNnÆ\®ìñ—ýlt4¤:šñÏŠ§˜«o۵Zãö%‘ºÚC¨{ðoªut[ Àlì(Þë|ò:}<ÁIÉíz´1õbGI’í}Õy¥ý{Ã>/Úp\ •¨¨ZX›Ì‹¶*Ù·2“í*,ˆãÇÃßRèw.³zø…V{ç+¸Q¡_³ìî⻨¾Ø•ÎÜþ L£f9 ˜`]ÿ @uÈrÚÌa…Ô•|¯£“À«žò̦e×+p]%1ÄEY@ôaìVÆQò…IèXnu8¿³ZÈåT4~IÂî“R;^`¬Á¸{’cwˆòZmºÆ3ëEãÞ*b‡;˜»˜Kyþ}˜¦pEN[Ø9ŸfÓò£™e§O“ â]G2?=–w8îg¬EíŠv¼#³. ø!ÿMW˜åyµ"Ú‘h‡InD¸À¿c¼ô#c|vÐVL¶‰x:ÆT{܆žwþ¡lœk‘âÊz4±c¦V¡J¥îø#ûLzÖëô´Ëàmûáy‰ûõzÊmûZXO£ý&œ3–̪†³ìÊ0™t¤Ñä%6×P7·ïéc—Œ¥<#yÇ„ÉDR#Îzeý@û­«8G°Æ¸Ö4g£? 6M ]¹7 clŸŒˆ¦7G_K¥Ê­nØ®’ õ=ìíÉ„ƒ!z£„Šn©—ØyDbL+Æ¡!G‹ †‹6Ùe¬ÔW-7|tŽ¼Ñ’›UD•wܶÑJ‡r½£xž¡ ÆPê>º³ƒ¬Ú7ž¯Y펲k²g ‹šÃƒâh¾áIÊ Õ[ s(d:·@Ÿ¥©Çõ¨ Ð-3){¹Q-Pe®ë×–Û†mCÕWy‰°gÒÌÙGí_'g0øþöÒ±žYEû,BìåœÍƒòï/ë¼W\ʨûðT[RÒT›)QµH®‹ª0~plíaëkÕäg\JIãž`Iù3ÛÎmtª¯?•¼¥Ve†sïžñv¢°èW„p•I=§iR⑜T7Gx‹G×­1»A} i&(>dëŠ.q5»“áo6éÉ=ð(awXy4º¨’±ÿö<&x4Äš'˜ÌF?ÀÒú¦Ã÷bФ‡rN¦:ú§üÝ"ýaß!!FE©éáä£n‹êƤ×íØùAmNn§>3ý f¨´ Y2uéXD£†ý¦yþç¢Nš<‚ŬÝ„æ­k´zæG4t¸ÐY¯=³#@Û ŠŸAíÔ謷1agd…Ü7Þ†«êc]?ª% ¹µ#S„ˆÐ²²ÄÜ_l%Fý6ò) f…+ž¾vøZ~ïB´ª@WA~CÕx#$ˆUú@°Ñµ¸lh­H…¾/̬2®^"ÏØ$¦+³¡hiSůÖxnÒäÁpÛ³ÏN®‡’\Ê=(—ÓL¶ÕäªÖ?-ñsÞˆãl¿ø9AÒoîäÒ[D¾½ÖB)K·1d†Fýç¾Lª!ƒ"©0þçá³h¡€Ð˜É‡Õx#…B¸7Ln­ÈQŸ_Õx·]àI«:nÕl°Z(—)k0à³® F|©_¡Á9•Õv(5Z˜uKUeïªE†~.U6.NèÁÌ¡õÒúZ(žµ6&LLœ%—Â(c¶Û`ÇmM%3÷ö|åQÂ÷ñ—-í]—$‚ëUÞPæË(•%®=éPS#ï/ûÙÔ½-{Œ°X3ëy^-ϯ¢ðeÿÖà‡šfÞ[.¨ «{HA9.:îë¦n^¸7Þ×næOl¨ºÍöò(L'¯…üÂa4½1?Ê¢X%üx¥Ä£æªÌdRÂv®+õ¡xRÏÜñНN{ybüÆE“ Ž"‡]®‘>z:1ú0h·?26ãͼhÒiîšZu°3 šž 8ˆ4L±KT]á l@½þ™›*F|øF¹6гBiP@OfDÀZR‘á+Àô†)§÷°ù9N-“XDþz º¬H…Ÿ‘±G˜ô;³^©4û…†w¹ÔÕÌ‹3ï’4ËNû¤†E©í›ŽuÍ·‡C†lˆók½[Ñ·‚°ãOè‰vñp»^IcËNðÁì²ë•ËY@ìŠè¬Œ’žmAÎhðÚw óïÃyátâ*syÅNfsV;äõ÷«J©Öƒ>Ôè24Ãilè/<íR‚ oºpZ§;–J0Å,?ïæÏ8‡í߯'ؼۋzü¡%/U‚$C¿£æÍÄš0Ò ©ø5-¬6‚êHcû‘чgX™8lÖ`BDãDÿgyÁ ßUª¾ ·9^N*- ¤ûûˆ±%A·M_Öäðt#ð¯Æi\•ìö¾ ù®ê¬¡ë‚ßYO%°×v…©´Ï«ç‚Ö±ëÓø4HøIüÉ¥¥„Êòø ^ïãMúýꆦb™µÊéõ6æ¼ÔŠA’ï4_÷‰b[)Sj±¢tÉã©í›;†çìÙïù n›x”öo…J»š–ý¬¿Fœe=°Ãå6>V»¥0üŠB3z—2ëx™2 Éõå쮺\1Ø|=¼>à ä|mv`œPƒ"–R§—ÜS1;/ñ*O>%û$8$T*šY§÷ ÁÇ¢“ŽaéBõ³›ÐùžÓ“âœQÓèwÉ;ôv[»,üYù,³×hÎÛ”¸!8 ® ”Uïï-ʸڄzôle UÉ}ë!îÜŠ|1Ô÷Z<ÆI1Þñå¾Ôº {¸-~¹N@î¦ÙE„$šæj[>…oÂhðÔ 'ó7 kãÀaK”’Ì'v‡@˜›ÝümälzáÃT™Ø«j¸ø•4ºÊu†©Î½ŠwŸ súD/cO)r¿T¦æxd‡­²»wÄtÖjY\¡L×vg“ U4*£+ƒ yÅ?»^|í­$r À‹¬ùÜ]ׯiÎä¶[6þíóÕ˜»®éS5 {±4¦û,%ѯÁ©ìι¥m¼ýábôWkFo‹vÒGÐ3y ²7WÑ©g\÷lÚ¿Rê„ Ðªàc‡Ä–~PT,Õܾs –ãq]îë<-­Åqpf6|þ£N…ÎWL€MbØS“F/ЏêB?‹ç:Cx(ÁÏ4kÝñɨA:‡’½ZSŒ‘ÛgG<4U:VôT­w5ü>IŠƒEW*JO·ÂÅ|Qølf~š;Ë{¾‰‰]²¾ïêóÉ“V , †–—? \ô•ØX1¾×y¥¿Ý¬~éOð¾Nà žºÉÜOͯCŠmê#f…p¤»ú¶"ã{/ŒZ£`ªAo•lbÙXR¼ Ÿž»‚÷Ë–î‘û¡T™®ƒâ¬õ¨‹Êê¦ïȲ[H@•ì9¼ïDó=A:7¾¹åñ,—ÀšFj Z’…Ñí_h'6âB,‡—øØ—ì¢mj!DB"yÍcg£ÈCÖNMÛªí*Ð"÷ˆ©o ñ¤GÖ3œôhá $/ÁÊüê,,pú5gVzž1dá2{ ùY»IŽW5Æ£‘¥ºd…ñ—ïø,ú5·lRJ¬™b^ìø•7Eó@Q…Œ¤£œ Å¢~p¤÷8ûF£^$a˜eƒÁÁä¢Aó`D­¬D-͘0*3'Ñãtೌ•ªpQåIý€ç•;Ïòu—muƒÇÛëûõ$C"¡(µýåÉr†ŸXmtÑ¡®²ñ/Pbg*닺h8ÄiCØ®p´>ŸÝŽì'mò^?5Ly¬e=½`™_PÆ–Ôk!‹YIã~ó2F+ÁNç–Äsd•ŒØåä~Øï·­ï<Ìž +‘ãŒzæ´Âý±šêzt^.®>¶2ZÁ¡FV<¶º~»ª“°»¸}³Ygk´Œô=°N“ÉX¥è@G뢦ßA²¤vp~))ö¶Y”a |rÁW#7 ô–èc¬×º•ü3ñÂÑ"‰Ö~vPã­Ô,ÇÞBæ,­ðªYÂGÅ.Œ“HìcÕ›““&Õ”i\Ë4™îÒR@Ú0ðšd¢_¶ÎžöÓ¶ I;tÎxú–„—Ù7¯Rÿ`æÆ“9¹o.rsNÎ~-ž,ÉvžìÙ»A¡Ógþ$¸"9¬OØ™[Í}Î|P¶7ó³ÅÔ·‘¨¤óõ«Ýa[7åñÛé%ö’Æ”#ílÌ7•mò=:’cµd×:õkN'Ø2¬+0o¼e1NŒ©Co¶£Û.µ q¿E@ ”×±w”®xr÷iŸ7ßÕ)¶ÉÏÙVt ²ô­úxÂÙ×K%}™jûˆ oòœHŠÒèˆo÷<Ìëûìkæ¾Æƒ‰1l¯ýó ‰øâøc¢>ZòÜ`8–°¶“Bˆ?(Ëeͤãžõ˾FEÜ“¡ºž˜"vÄ¥Øþ2hò[˱+Ó×'ãQÃÛD9Vôð‡S‰Cwб Ož‰µÇ»¦‚ ?+5ŸpbnÅý¨¡ù²TÐñ¬åYÀ‰ =Ü^‘_,EÎÌ=Ò%HПæÓÀì1v…8XV„YM$z –¶Žz¾›Æ´'Zôi”÷rûù"¦_¾æÚá1Ez•„» ~˜)öÀ—ðŠ?XƒüNkõ-'¦¬:s;Þ{IÝDGe9Ÿ¼ZüîN6½¸C‚ûð?"$¢Ž&%»È~$½­=ÑÕwj×ý]>)mY‘ÀñÀýN›à˜‘¼ŸV{OÖ‰£õ³`ʆô²x¨}ð’g¥ëU×¹ÊrïƒNy®ƒ²…u¡`ßR¥ÂùcDùì‘ëÏ lSCOçBç{霚Žy„(5Ê»4g»D"DèƒâWz¦§Šh´Ä°¯Å¢÷.§zW"÷:b #CûΨ†áHkiçGâà”‚Eßd1m ¡Â÷æFUmÑ¿&­,l÷ÝXÅ [JõMÆÓã 9‹ \Î'¥«qùØÛÖÙÙ/Ÿ?‘! YZ°foÕeЧäAOòÏPªëý”âÏ×ËDßÒ©A§VçØ¥@KÍ¢étƒšù90ÈK.I¸„Ô7„wûÞ9Èô3'y—ÖHìnûW2[Fõ°¿õXÏ,Q8ÄPʪ¥} ÃÜð ³ÿ’?< 8éP݉Ì唕qúðí䱈ìEi®=½O E¶ÇʶwµÉts7Q”2CI—ð¥@r׋ʄؠ¨šËïl ¹ëý>eÓ/ç-ï‘;±½|Ò¦†»0ýFÛÏy†ýæ¹õzH5õWV%©ðH3sÍ #y^AÈ”¾'ïÏ㘃pº£¡Z×f3Ô§%ö:•¼¶6KoãávnÞÔN ±71çWñû®ˆž†•Ef°ÏjÚUôÛ¬ ö[g/uùJ6#ÔÁIÁÇ øî/®­»ÅñŽ,n©æ‡­D‹íŸƒõIWæ.Í £ùí=cˆ%ml‹”µ^°¨˜µ/êfNj²"Ìû<Þõ*¿ùÄ„6ÄíkÍdF“\&qN"&ëìÓ¹ #B¤qà,jrüÑÍ<Öâ;ÉÿIò}IÅcõÁ¡í81¹…VŠîè";/­*O Åð»âè,03»ècé´ˆük‰rZLpŒvãªÀßN9­³zæ9³"ÔO;~z6hkkî®ÀL½@Šýv‰¨Dqf Óêð ŸÙ\kVoüª d óh“É|î›ùÈ/ƒæj}~J&gÙæ$\6ƒ ø’a,Kõª×\Î.gy*¾¾f’Ã?Ùüõ&L3«YÊ-˃ïqžÍhã½ã³€Z£0VÒÅ$¶ ¾´’‹Ò®[s½VQA•BN–ûØ„mŠV£¾ŸçѼJFÒêiX Êxœ$ÛÚ¶«{–v Ž–z¤Ž¬[±µµ\É/¢V^'$©’›©˜N4ŠŒêKÀŠÓ]-· Q¯hß$§´±9ùøfZ‘°ym)ÑL™EV­¶»|AÂ<›Ê,XøÍ³‹S{7ïo¼}Ÿ"‘YBC 8w¶» b缕VžÙ÷ °C¯X ±Yê­þÁJ"| ËÅ¡ò‘ì+Ÿ¹ †ñ¨é¸T)­=<Üy’ðP8\„:r{fÅkó–[)¦Ô¸{?]¿±8,NT’ÎúRøèåÉ56|oåÄ™û²€ÕzA¤ µW+&ýîÚº`€•PØ7­ªéµê¦ç®è~ƒÝŽ´‰"Õ.3©g&µÒû°÷KS§ºI?XˆÎäòQµbF÷m`2ã·¦ô†Azš¨"ç–ž˜ _äaIÜvÌËêþd"qèôûØqòÏ'1;¨9"Á(ß™Ø&ì›Ò9æ¢XŒSZêƒÇ8ä—64á7Å4ŠÌò~õÉ®¹½°$úrdÜÓôô æÖ.ÔPit¾ARþ}Î,—^O¿q‡Æµ=S„ñSmE4ÛB¶ÝI(ÓàaÅ~÷eN{Ö7ǵ§É¤£‘ו{ ÛL@ï¸~DÎ!yŽ’t¹UÚØØ[pl&ô¶¾EBJtΆ( éÇ¡©4Ñ]&£{r”qDÓÛÜ#0âmœXG7õ˜2íÕr ÿ—SF“Ú^ùù6 ® Þ¨øÞ¥ãNC±Ò”.þ©¾·i’Õ¦õû_‰¼ªPϨebjÚÏ$ˆ<Ѩeqš_I7Ý:aõ­Ö¥ð]DéÞpê¸ e¤½ EUØF4¹)G–+'lÉ™Ôö@çØß²}¶™^-Y’ΰõ‘¦&}Pé´ÞëЊr&¥OŽÅ›ÝÒóg·ÊÍ­¬{úÑ að VzÜÉë]Lø…F‚¦†|ê£<"’‰sÃ9!AÅùôLNð×ÑÑ6¨°Öu*@ô9@­2H­fNœz^u`.5â¾þ¤ÚƒùŒ`c:z®–(—¦…–&³¾¿lÐsQ›n §eÛ¸ÀúV¥ä:Aêcê`çµÎ.è™Pùrsgsæ¢}ʃ‚Ñ à”+`†C×=ö£ªM“ªpøˆ°jê^O¯-.-`€¾ÀP@\ò­‡Õ~N¨Dàš÷?Õ T¿.ô93,2$§5_2œcÈEsª%ÎÞ¼eW´Ãªÿ®|b¬aW§´ ‚¢î~¶xØà}»ºk[9Œ:6ÀAkÀ¹r¨ZÂØÒ¥*ÃhƒŸ 0m9xW‚\ñT‡­ŒVúΨÓîêŽåîqÂÛû_#ÄD×kùUuúhLš_G3U×S EÑÎ#í¸h¤›.x†~Ê4ïÁCÖmBDA<òLÊá{Û^ƒô\4#Y…`óÕÇ‘2¼ÌNp¢f! ÉîòËg'®?ËRß"l˜"jAñµX¨Y®´š· {XÕ³gÊX¸Ó*gçXË6ÂÐå¶,ðò¯@?ÒÞ?W}p5Køó¦‰½‘ZÇ&ÑežBõ­¢´ÁÖnåK7Q}: )^ÒFRÿ‘6,›^ŸîÏPþÄø0ª3Éۄμâ'±¯SƒZÆbïf¶»l),óÎ?1-Œ˜e<loªð(|KÀÿð ê|h¬&-˜ôÔoÇøBV¹M½šH²ÕHü‰É¸ bWãêxÍ–!‰2VXœPnþÖƒïsÜ]ÓÔl˜¸9ñŒ2mà‰k^û!Õã’éƒ7À ¬®cô§oç;rÂ圧š¶më|¦¨2ʃƚ2a6R„”–á7.‚+µMR½dä‰ó»9[I`ìì»å-èóäàØÆ„ÌÎDŒé¦Ý¢5ìÿ2l endstream endobj 842 0 obj << /Length1 1659 /Length2 9478 /Length3 0 /Length 10550 /Filter /FlateDecode >> stream xÚ´T”ë6,! )Ý0”„ÔÐ-ÝÝ]ÃCÌÀÐÝÒÒ Ò‚ÒÝJI·„ ÒÝH|èÞçœ}Îÿ¯õ}kÖzç¹î|®;u-6 +˜%Xue²s ¤T´œœÜ윜\è ÚWðßbt]0܃ ýÃ@ ¶p}”I[¸>Ú©À E7äò qr¸89ÿeƒ ¤-Ü!Vv€" vAg‚9yÁ!6¶®iþu0˜@AA~Ö?î G0²€T,\mÁŽA-võú¯L"¶®®NBìŽ.ì0¸3+Àâj л€áî`+ÀoÂU Gð_ÌØÑÚ¶—¿äZ0kW 8ð(p€€ÀP—G7¨xLÐRP¨9¡+ÿeÀ ø»6 ;ðßáþöþýãlÁ, ^¨ Àâ¨É*³»zº², V¿ -\`þî ËGƒ?7·ÈJh, þMχ8¹º°»@~Säøæ±Ê2P+)˜£#êê‚þû~Ò8ôXv/Ž¿:k…y@}þÖ¨•õoVnN:Pˆ³XAúo“Gúd6`W/''§ì {‚l9~‡×örÿQ‹øù8ÁœÖ$À~kð㺋…;à wûùüSñßXA@®K° ŠþŸèb°õ_ø±ùpˆ'Àˆóqö€Îß¿ŸLÇË uðúùŸþrh*JéiH¼ü‹ñ¿u’’0O€7/€‹— rø~ÿæßøù?Ru Èß—ãüOD¨5 ø‡Çâý‹‡ûßcÁô÷Ê0þ;ƒ*ìq–Á¦ÿŒ¾1'/'èñü^€?.ÿsÿ;Êÿmôÿ÷B²nÔLôÿµ…#ÄÁëoƒÇQvs}\ Øãr@ÿ×Tü×*«€­ nŽÿ«Upµx\ ¨Í㈳yØ9yþ’C\d!ž`+uˆ+Èö¯AúW+s8@ `u˜ ä÷‹óèÅÉù?ºÇ­Ù?¾*. û£?.Õç•‚`V¿·‹—`‡[x¡?öÿñ|€kjöü3ßv(ÌõÑðÈÑ` ƒ£ÿn+?€Cê·èâ8äþ8êÿF‚–ÿA‚п¯À#‚9<’ø—ä7«ÀÇÈà@‡í? /€òøÎáð1—ã ð1ò?=.ì Àáôø˜þø˜ÈåÀáúøHÑíü¯ƒÜàðÇèÏ*<6à_øÏs{‚Aèó³0p¨]MhÛU•¹ÛÆ(VßIÔšÞº ©û¦F°”Èõ)÷»7_%º¦¾¹þŽ·ËUúÐh¯OÄioºâ›þFˆh¾®í©µåVßq<Ñ›]e7®ŸJ†æÜP+¢Ã&Í3ñ)fbVç㙬m9‘M.+mQöØ1GcÞ ’pc"†¶Kdµ¬–˜šîP w9ÝK)»}Þ;ÄŻַPΊYM'ßÙÁrR:ËÚKÛêá#S2L1¬÷ÈüŠg >k b²tÖiÒÔŒcW~`Õºãá¿A<Þ½/®ÊöKnÑĪ"Wf+ÒaöbËôS6+$8d¤ÔàÂ&$Øù2ÚoÅèØžu«i³ÿ.-ÂTäÄ­NQ”ßónÜÓ9õ¢®°)æyíGd?RlËQëõx‚ÖRRRc«Ñ«oì ‘v$^iˆø²eyKµ©*ã|5—€äº yQgåJÍš‚(ݹdµó@ ªA§†ÃâSÍDc†lò_úZ&˜0¥Ì°<ýa˜ƒq4OÝ€•¦è­jÍ¢ã) ZÀ""«Î×…jã»-·’™J˜«ZF´Ò«ÄÊÒTܯ‰àë›Æ›‘JÓì/,ÎÖ.û‹Yg%ÔkšQ^<°ì¶ø{1Üã²/ßp(?Í­:f ŸZbŸP\è2}ŠãÒMÆ™œV“­Ê‘ˆtüŇª hРª"¬ Ù%‘ÈŠ}AO£ÿN_ab§q¥ AË¿q‡A–J¥»²çÌŒ‰äYÓ.™7¶Wm0Yá–·Íí…³Ì}Úv{i£ÀZïLò¶UCT޳mø½†U}%« v2ï‚'d`åMNñéÅ=K+²±¯ÐnüÅÂÜUu$rù¾ø[:!’€r¥WÃüfÏá”?t’µ‚Eª1iOY„Bí½åʤ¨Ó6Z@èkׯ¨Ðr!Ù3T´ooÛæ+öìÑ6X°»›cZ%èsx:RhÕðøå=BÛÖmh‚õBoëÇ£éfHä¾…ëú{P&¬ÊZôÕg½§Ú0dŸÜ«Žl;IY_ß¿Á*}kC,öP—\î”Ðé¿ì“ÿú³Æ¹q^ïáG˜”mº–îŠ N™m­Ûu)Åàr™GºBR¯°3rÜûêX s}}î>ž .ÉI³š6F>ϦÊ“ö{Ît¤` —ç ùœýRÒ8.t…(~G`_z·–jP|…®@¸phÝÊO{…_Åý4}õø‘väÔ´Koð'LŽ­Ìq©É?™ù`½7q¢ :«|ºkî@Ö¥ŽßÈï:È좗ɮ“'<),uÐXq°_ÓãÏþ^­ÀÏG4hÖ™xžx.t¬øÃg©ü¬åFǹٴԚ°¯®ñÚH2ñœ³BfRÌy„;ªU£xçxÏáˆr!n7î¥û*•C­#¤î¦*.D¯Ÿ"¾Ã¬£Ýýh’™ìkæp)÷^©H¯iš½6" ðo„â2‡Q×ÀEã Óîr¸Éóz‰q¦œ,RΚª °ЦÎ>î©-]…±‚rxÏëœgŸm‘„´ˆ¿]q“¡¤8×µAM ©Üx´Xuê’`"£œD·ÿ"v©ð¡ë»³Tã êp2Ÿ'z x(OeÒàgë &®• ÆFz=QÞ‹Ò*ÜMåNÉl ÷¼IËÈ¿,¿«$¹Ê1QÓ/"ß´¢¢Ä¤v=“L2ë¦Îr@Zï4gsGr^ÎÏ·*æžq=ƒ&Õçu°åÄw×I4–Ô“Q2OPØM­«øøô~»TІRÒØ±äÖ%íÏùŠ|š­ ±ŒTôðÏ-xI­pJÅøó[:§µBJv¼èæÁ¯Ï¼bFÅZ_K²Ê‹õò«ôsÖ E ¥¬¯÷7ÚÎQu]ëÏwŽŸ¦ÌckÞÝ]Þú9¼zž~[~-À0E›èHÊU$d8 k‰ôEv¶xOòƒZœšS$mL¤<> ©²­TÒñ\~´q’Ò5†U)WœÀj­EÞûçÓÔ¨™Ê0B¿“¸«RO‚ŸÍÇ20ÎüD©±.>øJ”,úƒš±KÍïDã ºå»Ñú€êB+«'˜ï­Üpx„Ù:}‡:ð 7UïSOS ¥uÄP y“À¢!¸Æ‹nN†,bÏô]îv˜¤§?É:ýÊ&B-ò³‘,(t.Ø]WÐ6a¦b»Žq{ÌTyÊáãýûîMºLÿ¬©*ÆíWÅIè2Ö{²ê×㯳 éj”æ=v©Œ‰/•½?œ½}ÅVÆ ÆˆæPò°„ÐíC?3?M ¶œÜb¡Óß¿b¯ã<_A~i™¦iMNaÑ0!ËìJìÊ5þZ}&®ßƒ¡Cå)G…V|Ÿ е8Çù·úuLÁ"︣â,„H²²´ýócsÁû†¢Ë¤“ðMÌ~Œ™$¼º7zñýÂVÞÞ™=çFöÃÖߘDæ&Ü ¨òv-bŸOc2‚g±˜ÀŠº¯œºÌöâÛÑèçÇŠ°¥ñ7<z§í¢½7¨:´œè*HIQ_)ÿêPÝÿ„êó.+Äu snŠrû‚íÃ~ü­;ˆ–`êA)Ú¾Ûq€V‹èRëÕv€´k- ËPžIÌC%•)¡ñ${fD¥iK;Ï¿NÝ”ØéO6HÿÚw†n¸CÕÊÑj{‡Vůe5ÏÔ®—²|¬Ma´’ï)@½øN}%qì½j|ø5·W=+ câ—§Wù*þª,ˆ¹Ã-Â=uñ´Äp·D§-[j2ªè•-S49‚Í¥ßÀ‹CÅ M;X©lºcÎ$ú–…K“}5â« Kï'vóÂ_jÃkôª÷µ°a…OÆ®Òë™±^(ÜÏ ‡»­Æ¿[ QΛÛ]>GcûyGÛóðTÐbRWVˆŸ±cÚèûÛ·¼pšù±5UÑB9n²©uË4û&:ê{ 4N™h"Ï$ãÆr} <ÈsióüYQ¸t­ùÜÌceÁü\8AosËo?v]6–£±Iû¸ôïbú¿ê%[íâLù°»õ]±a 'êË,¯ËwÑ›±,-ýg’°¸·Ÿ7Ý'öu‡x¥?ã9þ¨›:èáÎfÕ•BY‹x»¹ŠId‰ôjyˆ}/îu/‰Ö·ˆ8ù–ƒŒ®Ùä†"Ñ"¦÷­iÙ"¥fêø@鉅è! ×­Cû0ý©<Îù, QUÖâFÉÈEªå*å=rËw¼I…{]±%Í H&yµÆµV ·r›‡‚WmŽÎzCì¹N¾ eǤõðž’jÎù[G5ìÒåÁkí2seä×Fm¿ž§v%5HJ˜Mô*¸Î ‡ME…d)ŠU!nâ„ º”­!Yͯ옲ßh2²'naúÖø¨g r¿·$¡+ñ†«$@µ ’Û2aLM„êÕòâ/$¡ÑÚ±¬÷p¯MÔ ÚÕÒ/"ÅóôÂRÂá¡6Ñ÷l]]‡M@=íK… ËjFÐ BšRáø ’âèš{-T‘S`îx Ï+Éõïúdæ«mý™#.FU† -IþþšXHìfh˜¿H±imSÆz{»Ì:xÙ®§Ó 0¯³]_Öv&öC£ŒøW…™gŒH¶¬± Ο×~TRŠeødù4]û—¾¡Á™äTcìLÝù+,_}õ²°UP*ö8µ+D8)Šj’,×Xöš>rÈ&Zœ¹Œ3á°óèJ"Á´‡øo$«(X)Þï Å( ¾=›zÁjœé™+‡ÔÒª–ÞÙå9/|ªÃ-ú²9fo—1ÜW¯Vv?)ŽÛ;%¶"G‚zÅ]|Rþ±ý%ÓdgùuÊZÅsZA[.ÿñ!–æl¶y}™!.ýIx¢¼CdϦb¦ôª³ ëAÂX¡RqÕËÅàÔu¿–›ÚÉFžÖ«˜¨Ñ¼4¶àb'a!?¿”$©Žµü"ÛÀ R&”ù&&&„¿7öt­æŠ5DäKDÑ[ž–º¯{ÜŒ¥öMÑæ”úéj'«K‡®ÌÚãAQP—ŠLU_ ¡¾3J+ <ŸLƶÊwËùÑpNn¹©P‹:¥‡gJ¤‘–Ô¢²‘$ÏàȞѫÆõÖtFâ=^Yô(qvë°ëk« ¤aa[W¯ƒŠ¦^N0«L³·Õ€•*ÛOUl‹ÀqäŸùQd ᛇd:1­o~‡0ž¬f‚¥€Ã½F¦%*ýQÁsþPÈÏÝÏÉ<ßî·˜Ö¼SéÏ;¾F®mˆó`ßB•¹ýÑß©šµFÉßÂŒ•u²‘‹‡E[rQg¬–[Ö»<ÜÌ–Éü"'Ý&ù5’/ì¹/­]⳸ÀÖá³—R;ÛvŸ/;ž2¾Ø11|£z[y“†¹ýÄT¾·O›f 6ƒKKIÇbP®Ïý™öæ“x+)±iaçørdÆzZZÛѱ`¶N\D—¶—¡1²úôÆ]ÁvÜ ÃËC.ª¹v×òh½iÙÔJƸT¥åTGÙÕ½ebê…ȱ°'Iw'%<=EÀc£=;EvÇ0©x•|pè¨ó·%‡ÆÜoíäìÁ]9û‹&ë±uŒÒŸ}ð=ø±¶RE+a¿D“+„PsP:ÑË oŽ~~ÇöËMtBóÕÓÎô:ѱ˜}ŽDû`T.ˆ“ÓO;æg«ŠD”Šîᇻ'PŠÍ"ƒÞZ‚%3³·Ô7KQ8¹B5Ì“ó(ˆÖ5i¢áGÐ2wÒ×öªß'± ¨ž”ÎÍàLÄæëo5÷Ó¯´»É²òÎ}xÎÁKlzfûiZQ—/C‚¤Pnâ–Ù`7Eªë$€¦c](£únŽÎm´¶½'”‚¼ˆl“Wú§_ GÚÔí5ã©Hž.ŧ>lÕ#WŠí¨ ˜¶™&3 =»G,=1ÔZ³3«ŸucÅ kÁd™Žé?ù[ü\+áþø­Ó›FQÀrÍÌÜ–ß žãmê8t.p.éŸÐ(Jx¡õ˜“¾°b$`¼ÁâZŸÙx® êÁËı׹ç?ç6§Yè¶CºZ¹m[E::ØÏ/|† …_ì_)è_[™?D˜•- »Dü¹tÚ~žöIµ|VväË©´mŸƒø!Ú >ÓaQúÙrûhNÊ;5^js,¡(üE ¢àmn ¢Ä%áMºªÙQéuœæ¡”ÒZ¼W·ŽA‹Óع-¯=Æ ©C#+éæÈ†Ï¼JX‹ž÷„£—Ü"̽SªäìNO¢œöQ`ù Yy^õ7wÔ{bWPo[ÑK8áÓ2Ç 6z ð ¦Ÿ6à.}XŠÌÈ+R•ÌáŒràÈŠ:Á¤Ž‹5[ÄŽË…·ë[pu¬äõäYá4)­‘ž5—Ü »—Êǽ—¦t²P?§uѵ{uÊN{(Ü‚qC¹#ƒÃPÁhË|1Þúð€ZÊÐÃßfb6Ñ`l×ï,á6¹ÌÞ‹Ô’/tœ2£.A–›Ý<ÈåÛìü><(‘Hfö£qÏ>™ÌúD0è5q ãû}šït_;íŠ.JÊWÎFBxSïßmÚ?´äŒ a° ë_T½“+$­Ñø*$ï?¼=ƒÀ$ýýšåMµ×Ë>Ø'dbÌe$: 0ÊÊt¢v;Q3+¿ N:}o0At¬Eb)3sÐü•o-Mjveÿô;a·»PˆÅe¥ÁÁpº…ÿ™ÂLºŸ¿‰…eòTºýáñEäá©oú$~nÈfé­îV0áH_° &ÖÆÁŒM:ë«mîp4 1¹BA‚Âê}N± »køÌ$îµ4ëœ5­)“/ïCˆ­äÓ(’Üž„’û¯0èÚÀ6Ä\ÄÖ»„—*Nw< êq~Õ9#Y~VHÙö€ÍÜÂG\1=ß·]ÝlÑY‡8ßÊŠìdÈu³p9è›È9ŽÔÊdÔehøÛéáhSĉråþašNÕmJÀ;!óûNIAÅœñ˰Ús ž*—låtyVZKI¹½hµù"þ¨D­5OŠðÒM5Öyg’cÂŒÛvú;a³H'Œ¬ÿÞ]jm-AE¾¦Üº¤Ú ÂÌî7‡^ww­*ã¢ñ;LÍGP™›³ìÕ-ñì’‚AȸBu¶à‡/©.‡f [”µž/„¤fØÍr]*.WÐa9>ÿr ú¥^µÐËQ 5“ÒŠwˆ-½ßPíGl¶û%u“Kù&ò’ÈLlIéÞhÕœH?| R€Ñ±³Æ<·´‡TP­dÇëRޱ"Ó‘¹Á©‹ÞÜgtŸ/G±î¼5¸köSÇšLˆ'£¹²Ç:ü„‰uÅpÛµg)O:‰`qßË)LöÔ³¨¨/d°úH ï ¶æfZ;VÿË*o†d½¬ a‡ÎŒ«œ»ê“ªÂ§õ£´ Ÿ¶ùhÞF‹qŒ™Ð§uß¡d4%ð+m_ÂwW°³,ÆÙ‘8¶D¯¤Nwçž„ëU,„«"ÿÜñë«'P”Éi÷Žl×¢1q—eiޱ„'õ%Ë(‡oÄó1ÍUÖÐ'¬Ä¹__Àd÷Â@(­ñ6…ŽðÎâE _š2ÚôϹjßú¤{Œeµ7ÍÌ 5s¬jÖøÔ;ð`%Ý.›pJ*ú¦•–éö³úf aUaq©ÉS…#ÌLÜ–áUôx˜WæÐß{¥Ø7`º‘uœ8Ü=¢#éÁ¥jÂù0±ˆž]ÞÔyušÆë‹íP;vl™“¸)⟚£ŸMXxå$öåèç0 JT …=ô×ûpÏÌÍw“r'ËwåRk_Mß É“B5)©Y/²¶¶9¢{ ×F¢8³§‘>Ì8\þ†x ñLáí^®£ ¤QÞ:žß®·ÀTØHæ]¤!ß½7p¹8„àNßÈ”ÆÚkЋ‹NȨOãn^A*çHË. d‚Ï:™‹¯l<¯f̕䀘ßdŽC¤IU‚ìí¨ROòóóhyÖ2ÍÞÐÖL–ãyÇÈ$Ó2ê–ôÜñù3O¤sé^½¤;9eÎýËß›—Oü‚0Ì<™ÚÚ¾Á=>z R-Â2ÛÒcu½ÁU£“˜4n1q#=â©ÖOÊ0úÐüI+ú bé2š× †e¦|õý~˜oëIÅì¢^¨µÿⳋ¤.·›Ä'{°™Ê[×´™ŸÉȽ]yíÝlI3W{ÆÃ1œgàÀйbÁ@eÉá“"£À47fäÛP¢àOyiwK›Ùw”'Íøìå5Al+ÈÅQÑ6¥hk­úy¥¥‘g3o …Çkd·“„Vh"¿å¤=š¸_)¦ª.Œº'z¢©@ÊÛ}ð þã=A‚ šô¹¥—Ç6cÙ;C ½Pm5ú”žö¶íYº¥m¯XíØN4ôÈ«NÖ•Ȇ²­?v‚[Q÷ë×À‡ÓyåOˆ`ÁÍ\_–®Ö'Fïè矿‘­Dê“N*(sê }–Lƒ‹BÓpÕCÆÍkØ£­g‰ÚB\šxÏJã^Ë9kýõ™~ÍÃ3RKÎp7lÔP¯MW6¯…G^n–ÈðµÁÌŠ½à©âá]¡óÞ³²œPPhÓ4dÂ)[Ü›‚lŃé¡ìØnW¾dfØÂœ|²”è÷a³ÜVÞzŸÀÔdŒíÎ\UædB ŽÌ³þÑ•}d 9der|¯ûƒNG•'—FºÌ5±ë²@}y<ÛÙºŽþ3oŸ7×|ti¬âëd¿¡îiæq=´mï‰qžéÛ?_mP½ø ‘3Þ°™D…þv¥i?øa>î¶,ÊFÚ1<6û©…–¸”îú<ÇoõMéh»ÈY-]*J¦È‡Ü7Ö” Ÿu²ÛŒÞ´/:±}Ù[ ²~¡të¼RÕ÷~j'gö3ì×=Â[܆aRaÒ³ðŒ´ëôª®Ø\ýݯHËîôdTƒU$uUëò,ýÐ5÷†‹¯¼á§3éJ<»ßiI]晽©@~ãµ<­Ñn6èŸÍX«ôΧž3W@õ˜ŒpïˆL_‰F²®1˜v؇£G­ Ć&nüð¤Æ;JO|ó‘Û™²™0ˆí.ÒftšöûÅnµÀ²½ù졚E   G‹ÃÆ~_©3tø`ïÍE§"F¡Ð>¹ÅEZ:uŒTÉU-·GR‘C…ä¢Ç‡P®¾ v¼Ã iáRk¡‡›Íá7,§|."`ÑH©Ì_ jƒ!涺ø³5S ¢+Â[Ýg¶P÷ElCi—=^_§ëD¯®Œépš¨5…±b©ðñÔ,·hs’˜Ÿ¹ÔE_¼*èÆS&ŒÚs÷ˆø„· l…Ã"¤­z*­B÷¼ ßç¬ñ=Ó«M-5ŽÄ†ÄåÐ9/>d«©É{rí“ͯ’£%ïÌHV=¾$$—+ë‹mà» 'Íg“}–jåñ‹¥n%<2:1TLµM‰›–Üš•JSãKbíNËžer”¿ÏwÑp½Ú‘¦Ú7K–ç£NÝ9þeÕÚ{Øÿ¶Ù7L¥ù³-³Û§Èñö½2ÔåJÚ°É ¤óPÆ›¶G}ðAäÎ'|«>\.òÝ, 3SÞñœ ^%ž†…¹Ÿ_ø}ÓÆ4·ºÒ†ãP]F¤ë•<±¨?*©(ySŸÆU`Yi¥au6B„\tÿÛvU5YfhËb„5Q°LH1÷ŒÌXèwé3ÁÒÀ€ˆAÏ;µü!Ù,›ƒûs¹÷R$}ê®ÄB3_u "ÁzU¼©éù7])gªo*öJ“ŸÄuàg?ãvŠ{À„]¦TÖuÏ“Öû ´f!®%z¶%Ë&‰nô_S€3ÔE¸¦ºÕâ‚«Æ=L{xÌXX?¾Ø“h3{•֖͉[ zÝ4Ç(:µÌ »ß÷I=Qr¼µÇ)k¸+õ3ˆ ù¾¼U´¢=×W>_ØJE¶f]É‘"ïÔD\9º8æâ¬‘0bΦâmë4³^Ÿ“)…&Bu¦@ƒÓ=ºe'(\«þeI¡Ÿ|Ië#aÕ„‡vkR#½Þ/€÷"|Ü,Òãp!uÒé¦l²øW¤ªá;ÐÉäwºïûÓE~öFSúC(¡…Q_‚ôYŸT º‹¥Âé‰å T¹Uaó’×¢ï–k®”«-Gqñi.ô·ì;ÊÎH<Ðf]—é²Äf±/Ê`ùùw¿X¹>Â5é ->–8Vâ ÜpF5.~lz^«¾•â­=ø\pÍåþl3 ÆÕåú£’ ðJƦ¨/ž>c‰TŸàòâ²îôÔ{­H£(•®A¾žf^®´UŽ­£åµùT%™»×Ï¥nÂÅ„«ŠbN¨î®¢N²Ù¢Ò5j«äیɩ®8o^ÙkâVÑ jföÃmïYÉÞ‹› ¡Ø~_ 7¡Óz³:p|Ö^ÒRB/š ±8ú…åäy‰ÿƒN)Ì÷}J¶wÁܧòà gDéŠB7Á‘Ï»}-a¡òÙÅebŹÝÈÇKšàOBrÏÌLƒŸœ-Eâ|Sî0xr˜P-fNÎŽ’7c^U<þe‘˜ä Ážmì ßLOÎò>q_#Úu#@Ç8‰>åCq˜´ÅÐJ ÙÜg¤mæÝN>Ý\šË¼÷¯µqäñ:°«`ãçalCªÂSl(‰9V¶´Ë»æ‚ÛÝ"Áå¼"ÄÖ㇂fÈÁ¾¬ÓÖ†‘Bf™>üóÄ€_c­[sv+ƒrÇÄöéÖ’]KµU["6º«ÜKI®FЮ´EAe@#?6Ùï‘ÈOrQi3 Y”>ã?Ũyíë¯#õ½ÀQ_Wxë€c%wqÂÔà„èðë*¯¾Î—XËÌyð²ôf%¿’ ïÇÈÊe™‚ÀŽ®Òp›„•§+­­ßV1p³‘AC!ÙbÉØø4MškójT™ç«~Ü3>ï*% ú¨ÅE§¹}çå' dî9ªu±‚Ù¾D*urùþê¹2 Ò/H»kÇŠc2«Óîiú 4‚Ò‰´BÊL¼œxýï—WÉ9­¡ÎͯV¬Éý-‰(RÀ1¿lÕ®jý®FŒúÓVc&¾bÀ>·£ä.ûSÚ3¢º¢š÷xAhyÝ?’ÕÓŸ–£l!ôØS [ìÝÃPkÜŸÉîaN½Dï¹ÂL|ï*— »eôÅWá¿Vzª/m¿áe¯•ÏÍáó¼2ö,ñ2Ç¢bs¼Û{‡mšy2ô]ýëôÙ'ÒÈ †µõ„Ëä‘\†¾¢”9¼/6Š2\äµ9é¶]ÇrÑ-»–ƒ«BßÂ&o Cq°Í\ªªŒËÞ T°J£–ܼþ¨@~N_·ðºG¤?CZÅAm¼µà ™xn6-e(f¡cý¹xÖ²„ íJ”rk~E¥× ÞØì®/krHijýt%æ&‚ýð€8ÂàƒŠ•Û8¿bÜIwé[X:ÞLÐۙΣ ¾fÄü“¼ïzU:ÑÃ?¡-+ƒgVÇæê<”R;¾líÈ«; ½Ø%_ŸdˆZ|"~!›½©Q,+õa1pŠac´@Úk ø°~$è-›îf‡iNN\ų»íÝZí]”=dk¬YÄ“¸ ©ŒÉ÷Î*Ê\Îpž©Ÿ“]É›?) å×\…bQ× í3˜ëm¦¾èœ´!ITC%æô¨U+8:d|ëùß@Z†‹=bœê€iÝËß×UÄÃõʪòæÂÀéì˜ôÙ[㯿‡º•J ¹êØ\ÛmU}îݱHŸÛAxpUÿ² ¨M¥úQ«Ñ™ê1‹x“8ÛI/š½ÇR‡<•rºl¬š´ûŽp™Âã?-X¹þ̓ÀYVúYaÈG®üæÍ³`k®š‡ä&TQϧ%9Œ×O­Xïy<#±.—Å9ËÊ$ÆþKæý¢“ŸÝÄÞ¶Cq_Þø]:RJÔ$‰½ÈF%iÂCqb¥áte]sënˆ¥|pÑhÎ S_£×Eé}>õ­-ìûä¾É€Œ3dæ,§:çeÚ¥÷“%„ # ôñi<ó°î¾=EôöO9dÒ,¤Fx÷=`Ó ¥™ý²Ïd+;Œ\G½?‡t*ƒ?ñX“Ì=™¹¡–w3Ö’ƒØÕ…\ElUê.S§É³{u­$ÆGÝ_ ÆaLV¥+‡,Bo¹ÏjÂŽæþc¢ÈÐr.Zßá9m§e7ÏÓ^¾º[d0bÎÇ‹‹œ¬ØúBé âüé™cÜûô«%«û”È&jÁטvñ=Ì2ónzShÇ»M©%b«©_• Àz‘˜ö¯ÀÌ)VÅ¥Õ–¤y»ÉS®ËÅUç¿øéYl?©±×7YÈ!Äã¿NØä/›µW6È„\-Y"î”{d'Û¥¡$*f„'-æï‰™3÷´ ˜‰ÃGhœ²}:Âðn ïNéJ"3m~2Ë'*-qJöаÌ>ìÉm‘¶U-®]Í,L¾Î2Éb %­ãŠ›¾u›w1c$Ëð“YÌ3âkA©Y‚¾TÙ€ ;•Gs¨±ÑÞ‡gÙ+SZ¶Y½‰cèµÏì~eÓ?xn†ñÒÃK¢ž.ÚØœ¬tg6’æú®gÏдTj&»¼#ñ4>"2®IëÃ6¶:þÖ1Ž'fæåbµò“ïB2{Û|‹)¿1Õ%²?”Tg„:Íñ>;ù©&in¥†Š)0 ‚RÅ nÐè¹ñ‡±ûñE¿½9$ZIg~©¥òáCÃ…Xò.ükm3<òï©› H²§bzzI·šÂ!u~ªÒ!nA`­L—‰Ä€ ‰6xˆ³›‡i Y»Ù“,Ð's=¶eÙ7Ó š‚ZOg_$ÿ\¾ iŠå_ÉW3Uë0–ì}¨Ñœtì5!‰ÔÈlþ÷ìXçY)aõôž\Öº>¦…–1ÌìI×OgB˵vKsB’‡ÁžNÞ8R.š‰)R\ês‰¯AaÏÜÜŠÛªUïÔ±w¡¶£zSÎÎþý´ú|²Øºö–as ›{*Ž•®³î434\%B£ø0FG2mÜ‚ÙÛ%¤}Óµ/”$Âì5µ¢g™ÊïZd(Yìt‹|’Kô0(H¯Á†w¦RâÔšUvÔF¥$“ßsgÙ D€ÇÔ¾ŸˆýÄT¶ø’YùñöŽópWT\qýA ÞR/ †Ï«E™=L×í TÖ;IUaLvÎÿ8šxj endstream endobj 844 0 obj << /Length1 2672 /Length2 18727 /Length3 0 /Length 20260 /Filter /FlateDecode >> stream xÚŒ÷P\ÛÖ ã. A‚7w÷àî®ÁiiÜÝ îÁ-'¸»C ¸w x}Î=÷$÷ûÿª÷Šª¦Çœsék÷¦$SVc1™%Aö`FV&>€˜‚º:+ €……‰…… …’RÝ l ü¯…Rèäl²çûÃBÌ h †ÈÄÁC=@ÖÅÀÊ`åâcåæca°±°ðþ×äÄ7vµ2(0dAö@gJ1ƒ‡“•…%âç¿_4¦´V^^n†¿Dì€NV¦Æöc°%ÐâÑÔØ 2µ‚=þ‡‚FÀ vàcfvssc2¶sf9YÒ2ܬÀ–U 3ÐÉhø+e€¢±ðŸÔ˜P(ê–VÎÿQ¨ÌÁnÆN@D`ke ´w†q±7: Þj2ò% ýŒåÿcÀø§8V&Öéþ9ý‘•ý߇MMAvÆöVös+[ @IRž ìfÛ›ýehlë ‚œ7v5¶²56üº1@RD` ÉðŸüœM¬ÀÎLÎV¶åÈü ¤Ìöfb ;; =Ø坸ĭœ€¦º{0ÿÓ\{›½×‘¹•½™ù_i˜¹80kØ[9ºeÄÿ±ˆP~Ë,€`' ;躛Z2ÿå@ÝÃø·’õ/1$/À’ÐÇÊù‡âålì €\€>^*þ¡°²̬LÁ …•=Êovˆhþ é¿“•;@2~¬–¿þþý¦™03½­Çoó¿[Ì,­.£+#AÿOÊÿ*EEAî/F#;;€“ÀÅËðù_–óÿoîK•­þ‰í>{s€÷?)@j÷ß4\ÿ™ š–†ð¿Aih~ÿNSÈëÿçøûÈÿ¿Éÿ‹åÿuøÿoD’.¶¶ëiþcðÿ£7¶³²õøÇ2Í.`Èf(€ ûaÿMµ€ÿYg ™•‹ÝÿÕÊ€!"boaûo!­œ%­ÜfÊV`SË¿'æ¿m€°ÛZÙ•AÎVÝ7FV–ÿ£ƒ¬œ© äNq†4ëo²QÿëQÂÞdö×ê±qrŒœŒ=PX óÅÆÉ ðb…ì¨ÐýïÑ03ÙƒÀ#Hv>sÊ_-åâ0‹ü%úâ0‹þFÜf±ßˆÀ,þñ˜%þEÜ,fÉ߈À,õ±Aæõ7b0ËüFïr¿Ä»üoñ®ðAü)ý‹x þ”#ˆÕßâAí7â0«ÿF´#§Î¿ˆâÏø_Äá4v†Œ•³ÍoÈq“ßbbbljãlkìlù¯”•ã/±ÓH@&NƦ@[ 9ø1ç?âÿ¬È¿¬¬ÿÛÁÿcÏËþ¯üÿ€daú/â„„h ²…ŒÓ¿™pü%±³ûÛ_sÆlö/d‡”Ý dkûgÌ ˆø›bü§\é] ûú/ $>ÈœÙÛýÁ©ùoˆ…¹•ë´©A.º…˜XüvÑ[üõþiIçwµ9 E´ôp°Úÿa‘Yý!}µùB ô;j.H%lÿÚ¯ßzH9ÿHr½2ÿææ„pÙCöò=¤ ßá@ƒþG IÁá·Bæy ÛÿOg9Xÿ‘þo_!·7³Ð ò¸ýÔëo™èw÷8 %s°uù#ÈOfÇßþ…\€Î_1ÿrsü%f&¶„Hÿ¨4+¤Ž¿i9ÿB@×? Í 1w†<ºþðÿÙVH¼¿£‡\ÿÌ`K'à)Ø ôLJËïцøüûWг)ÈéϪBzèú„TÝíÅ‚ºÿ!^=þ€ŽxþŽÂä túOÿs±šº8AZþûÙ¹uÿ‹ÿþºMQ–@¦üÁÖuÁ_ïkEÝw'ÞÏRîj¥Ñ2z-9µ»<` &ÓÖd®;ÝŠ$÷¼ZÙ– ¹^&ýåuÔRÖš¨Òöèýd¯:½Û†òm w`²èHäK?12£ºðž÷/GoÍØèNYÊ•Ï0ÆhD(™£Ì7ÉžKŽf$F¢Ã:wÇœ»¹ÅÊ|!•§Gñ9Žaÿ䥻ÁûsÞsµR͹ Ÿ_÷-1ì ÖØ4•—èY¼E¯Òâèõ÷‹9,´LPëcý¤Þ£d'|zò2Xx,¶NK¼Rc>m_˜´{ѳvÕŒèêŽ0ßÒ›»¹IJ(5÷ì …!ß…;Ñ›)¸~DTôðÚÛ\‚»Ñ9º‘;:©›ÔóÑ3ßBFÙÂYi]ÿæèƒ­€@t½ÇÓå]dYFñÙ«×zòØaÖ}Ï]­} BâÔ±(9óÕ›¢ŒFnÊáø›Ïo8> ×ð¶™@!è¦ÕÆ_–ÔøÎäx±÷Ìq’?¦›Æ#÷èéæFÔàa›4Y,Ãi‚ÕDjm¢‹S ƒ‘ÉÈ[´0\.÷™ïþ°ìw³jáé6Écèq…°ý»nÃòüG³×ï,èëŽÞ7ý<Š„›ÓÍ3öknJÕ"ŠT¼ÁŽ”æÔa^ÞЭ(úQ”ÖŸK(1þIot‚*/Fµ‡ãÇüÝ-zôB æ[Kó¦pE½ª,J\ѧá‘ËÉ! Õt¹²/úãqj³ÊÍ]/˜+?½¿)ßÒ#êM\Ò¯}ç›6¦;Û­ûÍcÄ}¨&º.ìó`€•¸^üìT&VÃnë{Ϻ_GûFbÑ¥‚ôk!ç`›Ã÷8Q™¯Å›ù‘jܧ²ôtø¨:3Ô”c8ÆÊ”äÁ绸Ö$°ÄdàLÓj0út?+~oa¤ªP cvröeO±#n0¢AÙc4 «…ÛÝ>[W>sq^n3{§pÅÖ‡ZnÏïÆž‡Ó¬D´MLéçWQî:Ô­Cåw‡œá’¦~ïí­;ضÚçL±ű¢Å<Ýý`÷7É•ÑËŠìöh®ã‹ÛA7_È/[9ŒJÜ=¼(~,5·8¦ìtȰº U"¡¡ö*û8_7ŠáVñ¬¶§̤æ¹&ÜúÂ69ѵçCr'Yå/:_ ši?ycÔzª[œ‹€z´ôBWŠ­ä5-™Ñk¼™©5ðx?ÉϹšU¤l'27DŸ§¹8â¹:R˜iŠKöÖˆÝ@%WÙ…Š ¶v»û°2^ÿNU5³\쓜A ç/Þw×"'›ôBƒ¢Gû+ƒ´‡Â u|%4ZÔ{ °aPÏ¢ýRåhøŒN cêù¡Éó¸:Vþp˜Á¢ 6Ù°¥ûT¯ü&*$È3].Ú–t6ÊŒÎ_O‘@ÕÓ$WÍR#Ø¥?£ÊQcÊmÍ¢S æ¾Î’ØPVdàSøá©Æ.ŦŠ!Ìõ!wCˆñ|ÞW;†Úÿû?I\&GË´^ø;ÂÜËGÛ@ãòR·±%Åj ‡ñ£ªªë­ ÞÏ;†Ø²3&nd[©hc_ûFÔg’ ªÄ»`M‡ù´Éôý¬òÝÚ^~•Á!FSïömX ô ©«”©°—ŽÚî4¼nO¸Œ½ëÍ3ÂZ½]ØHó¿]\P—’8„¯c쇫ÐamÙ»­ˆÈÓ蜮,e>Vz€WG¡4¢:&ò ¦y+×ÏÇ$vl5.Ç[Ðé.ÝÏøÆuKâiŽÃÝ“$|÷cÞRëSdFÃuN‰Ù–-'µÉ¨Éª#CŠô-@)±öOÿ&²¢¢ýnŸÔ%<¢£Ë8IÓàç…$˜Žën‹Çƒ93fX&DЉ/]_{ ÖfkæH'Ûá~´…õ´Î„é/uL“ræ%B0嬰Ml$x–Ó0êƒÿÊë2 «Ô`f¹„æq™µÓ5WZû雈u™&ÜU çûêLüc+’%·«ÐQo¼Ò·Ù¡®b5QÊ@ÏmI¸Ïk1F’A[²ˆJd]Ïžùƒ½…L´<…"Y`#úÔ ÐáÒaRuº'¶Ñ™÷³_•1]õ¸Ù¾j"-X†ÈÒ1~ñ9œ„Ž6ÏñÔ¿õ³à~°"Πr?ûéÐÇ nÌ>^%p£»wÌ9§ ìU‹ÃÀ·çÇo<ˆëÉZiDŽâòýí_c½VNŒê°‡ÌÜ’½ƒÑ¥d_<™›²~HSwèRG,A¥S˜(â‰)Úˆý8 ûj,<ºI€{Ý«FÞaíuï&-å¬Í6#+ìAÁÇéê ¢'1{Á&ݧ¡Z¯6'¼n Ý^‰òÜ…9©êM—xÞeÁ #¾cÇ8s`Ѧï†ûVÊGµï,s^ÒÅJ¡.í &—!Qws)‰'&7-þÇtC2Þ'Qy¹/D^s$ ‹'hÛï ª¯„þ3o1†Œé ç(n#ˆ;]ß­4 sk›ø÷6"V@Q7Á`‡Ù7+bN¥O°Fgìk­ T<#–.½h® •¥)º Ðó¾,crp¿Žò¤™îy^_G/ @ïéŠ$¯òÙÂ)õ&yWšê>yŠí 7éú‹®vüÜ6.º§ìšÅí ’Oà$C¿ #êt…œf-àE¨[ˆÖÛ½YŠáÕø%y([#DŽ¥ç ßƒº ?â0aý­;o¢+¡ô"T†Çr>Ñ3­C>Tè‹ÿL"Þ‰\õÍC¾Ö å˜vRð Å·0><“a^‡ízI³ Ñ ’YUh.=Fuº²¬˜i(#j…†_4°¨UH5'# o*”EÞ ˜Çû«“›E“à ïRŸµK¨T;ú$PõKÙäýCû ¸àÐ.„,iy¨Æp˜E_™ݦ$’áµ²„7œƒ_5)ôGÁj³@{¶³®SpQà4ù<h ¬³ZïZmqsíÿ¢èàø „®­ÿØ/“ßepÈWwQùjá[½|áCÜ Q?ZJ³­62:ΔØY˺F‹jöˆôîjDaœ¿Í_Y«}¸á¢Wºó9ùéGr« ,CùPfvbÀí¶‰hîäÄÐÓ"÷Êw©ÉœµÕ³ü­Òh(ö›¦láë5î¤ÚØy¬dB|8›¯[Rv_á‚ß‘ônà Q¶Lß%[Gªuõ<3rãP!>€‘uKÚÔñc4XkƇ¤à¾c¥`.×O—¢8a“ ä¨~d+÷zÓU#§ïXTN]ûDè2LJXñ?.· ¾F @gU;T3ƒ¿†z»«CqbD[ÔSu3Ý÷v‘>÷´3ùµ>ê½*–þ”¤Lµºûy¦µ…IŽt¢ J÷ÖYESôL*e‘ƒcgùµ ®_¥ Á§;ò—A¸©¾S樺)´¡å&h­,¨¾"ökr¬Ä?帠Ïó“Û£¹I4$ï„îïõÞ¼«±’‚ yßïCwDù“. ë¡ülæ\€›)­èiÚØ–QòÈ)å;î÷­§98d‹"ž3« ‚ŽÜÖ7qö¤îâÛ4Ö©/OäxKò ¦˜Óeý½,‰úåCU¢t84O©Îf®}ó›©I¯§ÏŒ˜_ïrÀ/3>ÊOÇIà>œ‚Y÷/É<‹C³ªDß7™ð>x¹¬¾èá„’6”\S´°w‡| áîù0ïdª(KÚpø5y™þ+O²Ê¦²õ üe‡’ugj;Aõúò}=¢`~ʹLa^35жü>-åª{±\öBGób4“§þ¸‹µû‚Ù;YyV\¡7 õCBoÈû3MJÆTº1ˆÎ:ZÌM›¦fsêÛkP,l}cÎRã9ujä&ߨí^虡‡ù"rÎK;o>Þ¬à 2_nµFÙh­ºìYìø%ýÊZ8}åCÍa›<•´+ü³¦ÓPIf½…?s’Ù+ÎÎÓƒÑÌiü­;º9a~ûé·ìúôÂÅ}ðâl×]½ZvÙ6u.¡§~Ë‘IçYSe$ߨo(,ùŸ{zï‹Ç= ·ef«È‚ÑÕƒš£TË)f>‘–3çý…*:Þ  ’HCàéþ’>ø¤€ì¦q—uÌ‘úm¹!kê8LÇh½…øM_‡>ÆñZ!¾ˆ®)Û·•°Ës¥U`Í#@cOlJ84U§0”0W\¿utÝÎ%;t‚ëÑGé_‚IݤA÷õ|‹oÆkCöHÍ‚úSü<„zBÕòĸEuS ‡ç›èe PÙÔX­nªNœo-]šŸÁ‡SÒòÈÃÂ{aÜfJ½…{#ÁŽZQ¡Æñ—ø5+Ux9|Îx”ˆ®$tä c$i‹[Ö¼Š2àÓ8c,çW1?$FþÜ‘'1™Ãéf¨±P²§æÁ~*¯ª&Ã#˜ ¥æ'~aÅ„m‡føQã_ël÷‰Jg+o¹’çO˜ø«Ï§«&¹9LXgâ$Î[j³Þ}á§¾)‚¯7(vʤ9»ò{èæ”êB ò¼2Œ3ž0@%$5D6K¥·­P'÷"±âª5tuÒTúŽ[Šg޲ŸXn´nÁœîÞ–_«8}20«Á&ti!vŠ­PýÎÅGGQN/ðg8CÇìHÚ™ªò)¢²•À–:ônbQúÆ‘Q8xB)š¼±+Æqkw1ì/}KIJþ–ý“a§]ï{Xæë~*×_\̯· P.¨eá Ú¶„†ß8Z—_¤Ó¢ŒÄeÌÖÑç4æ‹` NO9lµ•qQIO%‰ñ.Ø9Á{÷r;Õa]Iý¤ä »”uznX£©°2èé«ÿâ[ã®|€`à/·µ6‡×½¡ó ">šH~ßœD-dÞÄM’ºœ±îóº%A{tô#|Ÿý)‹z‹^=èÍ}ã›ë~Ï+Ù‘°€0’HÆvA;KK²ÚF²„BáU¿Æ'Ná ls±2Ýsß‘õwC1ÕõnìÆ†§Ò›&±Š\ž¡ÎßA=Ömt ð°{‹Ä{JnêpÜj!~S#’I“Ý,É9 õ}Á¦Ì*1Ñë|­$Ô{ÑÏ“«ê¶Þ2(QÅY(Dž£µëíÏ?_-Ãu“¤ CýÁ,ò‡ÜÏkg¶h|/Z7ÙC0¢öF,Ž»K´*;Œz¦#g¼‰7‰ïÑC‚ÀÛc7¾‰ˆOH@n:Á'yí9%®ýGæWÔ0F|¤“sí0õõñ¥$­Ð8<Ñ2Ð7R É/c F>R‡ÅYx#B´¦ +ðkW)/Ü›r¨d<¢#í±¶ÐÃL+h0 ’I܆y—pW¹¦`5¡q]r⯗ 9 ˜Í…³$típ3c ºïàF“?=2Fdž€T‹kŒ‡ ¯`I=9 ëAñɇ*àD¥L#ššóëaQõ¦èù9×K¬%à†|RdÕ6W[ ï*«»cG‡óvw¨i'жôƒJø—tWÏ‹ýÌþ s`øÒÇG£ÒÁ1`™É]Z«P…&u±û9 ZÝæ8.ò`>t›o”®˜ØuADuÒ Ë ¹S¡s愚XõÌûž´G½¹Ç92ÆbVŠZNù¤5…ׯeŸqç“dN¡XÃÌÞeaÉòžR¥Ë|„ y÷0Ùo»ÞhJ×&úš¾´ gERËÞ,TÁgRUÇ%ÝD¶)°Ê5cßTÈÐBÁ†SÔZÅÞ!*Íý4cž ë‹·~"Õ#8÷ô­áh<œ!÷U^eÚ¶…Ͱ>ŒÏ›&!Ø´ÜoFÆáŠÌF%˜û[llV°¥àQdf½>ámo~±âu(}c'®íyíô`­f˜¯bQ‘PPJ¸·*Ç:F¥ûF²†¢5$–%sŽoxÐÈø‡™.' ;éú:åî*Ïö3M:“ŠäðS½L@r™2{öÓÁ fB·y âKö„îùïxÕGb¡×çÔe˜{Ðj ™Í}ˆßõ­Ô-†¢bô ×u ­C‰ª Ÿ“8‹jJ©yÜ0Â)é%ø\£Q"Gȃa›gËÏÊü6‹Ýqù'uÐb¾Ø¡Ý}žÆ\ž•‘›8oX9 2ôèÚ÷–f²ïõD§Æh>}¶øz,Æù xOq¬ú³é%·áy¥ò¾&—vK–ÏÔºœ½8М E1¡]L,Ž_éÕˆ+¹€îÐ!Þ÷saÆ ³o‡¼°FÛ"o©|ä÷ì]²‹ýÞ~âøž«©7¶AÏT`brXJ¾­ˆc=djô^œí6~ªñÚ©Èt=¾[i^Çó\¸x@‡ºHš*\…âsBX{Û@ženLI£ð8˜*_È×<èk¥¼íY˜™,\ÝfÍy}ãGª\$šÐ¤EG¬+6<©”s¨à|ÄòåÀÞø#^kàÄBW+®ZðgΉä;Fîˆ@¤¹Ü%ÆîL:¼f±ê^¬C-¡"‘iëºý_v«ñ”âi¤P ìÓ°¸¶I±¿~,àµÚæ\7y-þKñ®Ž”„ÚM¾z—«Îš<ùJËõ‹‡Â„‰¹kfKÑO"*†ùPiÄêРWÓ_¥ôÍCNúp¨Ë”»Ü›ë©d°Þf¤¿}´zOƒ9šš÷Ó/PÏAqø ¸7­_Ÿ¿/cëZí¡|½ôd=«G~Ýê9í¶Ã?m eú‰7¥æ@MçË+;c>[§R–Ãǹ圚‰>œñ+l›6˜vÝŽ*J^kLe}[ž;‘¶ê‹Å­S@èâUüx|#9Sx××s@ø+‰Ì_t[(˜µx #·|ÜD57Öv™i°håd ÔÅpØì-îØ}„zN€Ó ¸Óˆ<ü#û¸UƒtçÖa¾\ƒT¯^^‰Äþ&ìi"˜1žéUÑm°À²Ö»£/ZÎß‘Ù|z^ìùêO*Šüšö=‹z”lë²y™žcwì§œeñ®9 =\¾nØõW‘ÄoÊkÉ1KÔüZ«DyQÒq»z•L÷‰”1É~¢ë×GYmÓ²¶7XOB5RŠòŠtzA4æhW”R„?dQ>¡NuÓk“µ,QKÄÉte,êRÏÏj®-w´+8 ï]‡Î(F½]-¬GMõ3“)”N|õ†‰lYÀÅl+˜i`Æyå'†è½œ›ùZÿáæ–’þZÇ ÁÎfkãþé±m^ñ©+ïøüÅNÉqHˆ©ì=±[|‡FáL=Ãá‘ nDù.-SýCÊþs²ŽxÏ +´”ë—³Š›°œ‚Û½±™õ"×sÞ%Úûï‹ìKÒ„û ´¦‚S¡N7,O=j–Tùô¤$;¶¢æ~îVé71nwð:¼`ö’×&Qñv§å³Â°Ñ˜¬&#fŽ/«¦Á9E|<ŸèÛ:Éÿþà©^8Fl~‹ô¬JLÁ¿‡k 'K¥ÍÈË0À]Õ¾?â:Ðèegà]°u"âœÚ •Ë×™ ƒ©ü'Äž?kZyçi¸©£"‡ªÝ.ÅÛ>Ïq;®ó–Ï·ó!¢I:ÚÀ&Åï Û¿¿|ƒ¡¿'·’<8«*p3>ZçüEÀgt΋Ãu²ÉòÌãÔì¹k—²©®ümÊûVKÕÕÏÓw¶(§ÎS\±\r¸Ùe\Ôu+3Ï®VQÇVú”Š ¥¹ï÷uBS{àzÕ¹…}\@z¨Ì‹ËÜG›6ö*´å[$k…öÍt‰T2½µ\%}˜9› åºÙi­Û[_Ÿï%h¼l¬ë‹ç0ÏoKÝ}=Œ&Gn¹$›³¾6H Ú(œ ñµÄXõüäGµÓïÒô…kH›J]| :<'¤ä-y§÷¦ù£KY]¥L/yn`aÅ-ʦ¹ú´àrZœ­–UarÄD•–ï†8KÄìf·–G샠fÜê3£,¼ª±b•3ùaB4òTk®?XàËž×h,|§É­&'SzÝCÓFú†Ê§¢6å[‰Tv‚½÷M3Þž:¢R«ЉIÿ[þ¢ñƪ¯Â 6Ò$ .Mñ%S:/r¶œNGÛ·б8îý¬Æ×Z܈ª…‚ª­¬TÞôs¦Vj7ñ/™ö¹Î„ˆ`Nf)ê•÷¢øN0ãJòêWilÐÙœÈknf’ô$2:9¤¾Ð’–z)"ìæ]]ö¤ËÁd Ù™Èò7ÑzÌ”J:ï·CôYõì^kJؤ¬iT´¡ë~Ì„#3|]eNøµ±¾ø8Õ§]uMQz@Ê9ÞÆEá‹]Ê2ü‚æ.¯ŽÖhÆŒä&?¯˜iˆ¦Þ©æ†Êº=~á<óúª®ø(Ê&ógK|ºSÙÛ”“]ùÕH/L˜Âap„æÌB™ÿÞÎWb%Â%]{óîÖ׳ÀÀJ–ÍÄ}²b©QužõнïÓßæ wK´ÎïôߨZlýíônÛ‘¯r2f ¿¨‰ÞDûªc²< ‘"U£ë±½.ºpmòNïGα’þ>q}'€:[Y ó‘ï.ÙˆÂêöã1¸qh ¾u¤Þ^ÅñM€aèƒô?¿Ü—ÑäŠÒ+*E^ÊÖ³}ÏïØ ²m:ÍêjÎï”?…ÄúǼáuÕó¥Â‹R2Þ,'üªúEoMìÇñÖñáBÑÇETdQúQÄ3ï'ê7Ï#Zj˜‹¥R›!¯=…÷ ]lÎXJOqYõ•ÖÛ[¢ðbx½Þ-¹ÍH©ª°µÅ“Å9ó¿[E͇l£mê"6†Þù¢7Xß}ˆ9@ßûtò‰Ÿ2ÖøâÍáÉ7+&¶m×ZÝ0mØ¥v¦>žXEo½UÄ5 c¶PVÌg߆F}ûenuÏ,nÔöI%aÔ t¬]ýâŠx ìÄ >ò˜Ý‚Ê{;µeE¶S& |ÊÆ=ËLB}sSÉ·;:œY›Q€™p¡Lúš ¯ˆ„–ý-ÏAuyÐÄš­qç­ÌWŠp¯R¬¿7“RX:ßð;¦#?X¬vš“omÔnxÙˆœŸ[rlý³§¤Ñ߇Œž°a¶¯wŸ€à¡ó„ÇE|õÆ/KŽ9U>QÍš»½R²ÞµÑù–o/S/¨ƒÞèyñÏxZóbš$M_Gr >fú>È$w¦Úz@›ã;Î+/tH<Ÿ&¡êUÆUžÅMò# Žr%Úü0U¬Vç3¡Cn¢»5ãc~Ê~TËÔIa°6ŸFï½êb(ñJ¡šòË™Ã*¥|P’„.† O°’>)×–²Ží ¿ëÈw‚k:êÂAàÝ]ȪŠ9?éÇ=!”§^ÛûP7·4_pÜ.T~§9Ó5,Òøg2šW#¸?V¾çì~ÿ•~ôJÊO }tÞã[3 ýîí´ï*˪µïP[)‰ˆÙ=õ•ig%Á ¨ŠpM~´óÛzCÈD%Â=Mã“iQºÞÃY+­ôô`øQ­we×v8FkÙôÜ‘ÁqqÔʲíd3~­Ù’H’ž˜xÛLþú̔͡n$\ŒÀ¡G›Gï7“b?ƒfg/× GùôéÔœÑJ7`Ÿ¶'T)ëHw€d] m!&9yÊëôC»׿qFmt¾¢yZ†¶ÓÁek©sUø¬Â+ïa3Á€è©~Ñ/aë26å-„ÉB<ÊìC6þ!â{>â‚ᤠ¬–Á€átŸû]¢—þHI^œ$Œ ¢Õõ¹s­†u¹²œy$ø½BHünkfú¹k+¥9F#‡izd© >Z§¡& ”<Û1þûþå¼­f1UÞ·k½ÄGÃζ!Åœ;Ѽ±Ògôl$7¤=Ÿ ƒ†8y ä×¹¢·ÆFíå5¨5iï|Ô†A—¢Î̉y˜B?Ÿ1î ¸Ngq0'çÛ]‚Ò¯Ñ,Ç‚-|…>ŸãÛ— WÛýP*¥eÛlS}!”¸–½©.˜Œ£Ø1}‘¾“IuB›H z<%Eõ –È-%ÆS[8aj°ÐÓb—«éW²;¥)b çþÜê¸Eõ@;~“ë4™‹A=›G™ þòú"ºÞº1µáƒ⨠®èþæ÷ùª&­“†k5S(%‚h&3<ó ÜÔ夕}¹Yf’"žPmßt`ÎÚÑm„ ¢, muÙÉÖÓàÎY°eW6¡üa]žÇvX&s«gêI9züwºD4Û>€Ûáµ”Â3–D¡i>œ^ñ2t%ˆRY^˙ٹ¹‘ë^æ¤|^Žï­æB„úR¹i„é ü¤5fý¨md­Z!±®Ÿ “ÄQI¸sc>ŠùúÂÆ¹­cÅÁ› 'iouQ|°¯e­N,÷ÒŸlLƒmØÛzûmj±ï tƒ³Œ“Ë=tfÞkBÆ´žô]'|•®…Ê ~z×2q™=Åæ–ûDfÍE¬·þìè¤t*IÄg}ÓqõáQEhƒ‘7µ¤Îu²©is#ªkŸ£‘+®Ž PâÙ^õÍcê¶ÕrX‹/ã\÷?-LOÞôr+ÃæûJ) Ajç7!3á<€<³b´ÌÀMPœSû‘ ?MÁX¶Þ‡f —¯¡..b™Ã÷»eý\æˆéüØÕñxöQ¶g[dYL'¢oÿôÖ¶’’ŠNGÕ(›a/ë§Ç«ztÄõZúÎ…ïDt8(ÉCêÞf(û©ÓzëÊ=þ¢Ï\^%Î1ýy÷áó,÷ÈX+ÖŠþòÙây,>½Ðh²¬õº8€áŠVã‘ýûå=ÊóòŸÈ„Õ¼h×Þüàî¾ýHìMᬒ+Uô-­CÑBÇ`Îí¯Çw»¤µ¢-k•§úÌXï¯v³%Bcy¨7Ä[œGÇjŸ_×ø ˜Ï‚úü’`24»Â¾.8åj÷‡ï8Q‹””¨è [jÐ/yWµôp§ðÚÝP™¿ž´Q(~ |Å!è;>Y®ëüDÔoðkIgE"gÀ¢Ûè©è4Î)½°OòœWznz°â» ~:‹Ñ’$nu<>ÅÝ2¸;S3Ùòä ’qÝbݨ8‚¶€;YÝ·Òe°vrä&@Ž ZI_¿PRKGOñU™ëOtpM5ß Í‡ïƒú0DäÌ&HÞÞzàë7Xô=Æ™Ÿ2ö&e˜ Ÿ^¥>kd/§ÀôØhyi£ÁlïÇÛ ×7ñM¬'¥¦iP‡j}íK?š[ºýÌÂÌžÜ1iCn5·œ…f3úFô¨ø­©Z•_®ÙòŪ~º{uà›DÑ%2Çàv=}ü¡wWµã‰|B3ŒÊ”• Hõ-Ké›wÈÛË/{ÕTh¶E†‹ôÅ¡Z¬ÝßÊkÝ6â1ˆ.BzŒåº¯ã¢¥ $¸Š5=#§7ªÙ4½yX#à ŸÌ|âtiÓ ýÓÜœ=uÙDxÒÇA¬Ì™IPë:U—ÚWåýõEæàò'š—ZFž|Á5”ÓÃn×b=ðª(ÑJ8Ï¡<™¥Ÿ2e5"0×”J©h j‡ÿ Ín7Íõn¶KÐp!¯©û8ºzÍÞäݯ7ÅÜö߸ÈYNËøÍñ«Š1£ ¬\p€E=^|í—vÎq¥mý‹4ÚÔçѯZE|íRÊŒ~Ýð&´«Ù¸qÏt2]f/“9Ñ,ó+qMÑní‘+#L¦%Öý¬‹-ͬçÐjöΪSñëýÔ¾fêVJã7Ó¨Þ®ltžYjä–¦Î}gaÀG¦ü^\VÓ‰ù)î¡õ\Ea,*ð•h$÷*ŽÜO·Üq ‰±Ü3öîX¬[˜ý ™n;Ö2wÉtÿ1Œ¶K;ÙRÛŒùتZ$cž#û§_é*ûˆPsZ€>†d<7ý¥FâõQ»4‹ôuáð;ÄÅuðË¡/¸£Û#4ƒ»In)›}E™$œ6„W–ǂױ­u:eú äΔçÒÙ‡ø`ìØv— ‘ìA¿<䨼wPU:CïóBÖòHÑȱ‚÷ökΚɗå)w‹ŽÛh'v=F/¤Mšs°ò˜¾|Šüþ±úëBӨķâä›Î×Ö‰¸ªi¯®Í}SqŠë®÷ÛSú³v—˜ç‡»¯ •ŽÙJ EÌÔûîÄÆ+¨c¶¨5šmë·o§¡\ÓHlá<ø¥³ïƒ­dN"“ý<­,¿ ˜¨`•×çãk‘ž~=v”• ’± ù6»Óµí2A8‘€O_ú Åèä¡3Ê(é7…w}É¢ç^;¸ ˜ÝáóÝe|e”uÒØBZF¸Þ†!‚…Jpð¡Ë÷´¾:rûÖ} [Š_~ß}ŸÔýú–†þ‡†º5CMëu„‹·màNj‘Ÿ×æêý‰äYñK ~¸!âLš.<ÝÕ°NÚ (g/caUvZ•xêï4â¿+Ì%C> ½Jí g¯¼;”¤Â6)¥kÀ¯ cmÆ{éö#ÀFŒ(”Ýü 6Éuu¼/µÉ»¸4²%…žÄêç|·K¸èßéÏZqU½=Ä®9y¦®´¾¹dzD‰*R¡ ÓÍûª©[õÏ’*ÇW•åñ™ãŒr t‹°Ø¡3¬Åæq‹f(! ŒÛþtô%¬ïJfÐît&µö®+™1­4oª4ó 2Øn4Co¬‘rx¡ß˜ß¾¤oËšÒݵò¨ÏÝ­f XtÆá ¯Q‘Ì€1ÆÄ ªÛ®÷щ¬ScqHÜ}D.ê!o1E¢ŒðònÃÍaú ’è¼3úY;_âØ mˆéœ‚”Å{cûÄûÀ³Dšºã}‘Niø×|ÔàÚ˱7&^Þ…Æ}u»wóër»8è“ÜëÛƒ9ßéßïêÜe¹í~å°¥uÁwòЧ뫬D5¿‡¢[ç(?q³ZU)`ÊÂÑ}èðk“Î6زAù8Ëq]Ûsµz<úèãˆ7ef.å.y—ŒiÉsi€Û5),®ÂX <}aÇÉGãv¨Ù¦’lax7ù¾y¤èxˆ©ÍÔ&Ÿ’¶ÖhÉPkþ:ïU‚¬~áÚ ‚Þü碾Q7„ž¸,j¤Q]ë“xD¶[^q­@­ ªcX¨•4jÎe¾’OËw™½šÖQëéÃΘƒÜö±Š‹ñVü}àò¡þm—íñè_Ò9ãæì¯¨½$Ù·‹äló¹`“Ÿ…%JÔnýÞ#U ©”ð·[³ï—<Žr@Ý~4Ýe_ùxž\Χï‚*«Ž©ûL^%¼ßª¸*ÊEõVŒ›Y™Ϙùînµ¸+&ƒÉœÚÍMNôŠËBaL¤ElTYOäOÖ‘^]„ù㎌ɢ¨ÍÅmJš2Y. O¿YcÆ›`ýØn¼Ô$†¤tu#GÌ̸hP.§WÄ÷wm`GNép`k]óÂ6-3ò%ÔH/ Dƒ ®SͬøÉ!p~~Ù¯>Ó×/×V¡i°¿¢íKoõ1^ÒþÚçûÅ&ëvJýþ6ø¦\TÐx ç0#BFòª×Iwƒ[œô¡¹ ÏŠ¼ìÕNW¼±ÛXw-ñ3“`Èíý±ZÜB{}ŸBþ¤JX£Ò—Ué¡:Š7[JWü9HT¢LÐnBé&1¹ÕY|I—¬Z4|h.Š<Ÿ"5¶ïÝ%Ž´¯âeCà ¦1ß ¿Ê<ô~‚ÍÎ@ 87"sл$¸ÐËb¢£°n¾pGµpZâ9‡¶‡Ë6Ÿr7:Áw˜~:÷7x}’bƒÙׂæ)‰¥©àˆ± {â¥"0ñ6š_žËyüÎo³.NRÐÊ›…¢iW×ÙhõÌ—‰œ‘—Ç[kK.Æ9!Kƒš²ÚÞ7…¾Ç®ür3b¸# †øèýœd‡ÂÎZó5ˆxsT¥ÈÁ;óçZ#‘Q“ð-p=Ûï€TeL$)Væ­qÌ7ªÏîÙÕóžcIܸ-ðB,j‘·IŽ³ÝŸɺçÀ–+¸Þ'Æ/¾¸¶¨TÀ k¶ôÀÇÌ»_=xõ¶×ŠnôRÇß¹­’Zé§-ÃCz™šm§•Í85ÙÅ:=OVêÔ¼ŒÙ²B ‹ý>"Ÿ™âé#ŒDÝu40ØÿjÍ’jhþâ°£:~‹ Z”XNeŽ;qNa/"øµJ“ÅÅ_óý BÊ”3úWÚ:6£ÏåÚ٨Іä;ï*ö2þ‘ ‹)Ûø#.ÅKÁ¸9å ÿà~±ÇÅXÊe¶Ö«S.µÌ¦X‘Fþî^uÐ;’T‹ôõ”ïy¾ÀÉyÙ7oà‚v[+[–7¢Ì@U#[…ßãUb~2UƒYl? °kŠí³¬Ñ“©Z½oÚÈYtÏÂlw4p©íýû¯_ŸAj‘Ûv£*yf~Âz®ÇkÞ=<‚©$Õ´ŠV;¿Â9Ÿ(((Ëh©?Ñg9 ÑÎíþA5Ö…±Üa=5ÌSðÙb} ®õšéÈ— n‡Gó@Ñ㧆œú€}Míч•s´Ø{URZªá²ðÏq_Z:˜gæÂ3¥/ØÚtÏO p©üQ œ_mÛ=µ_Ð÷ä+\™=2—5×0ËÜŒºŠv­[û1¤÷$J> i’ÜY¢=\`½ø Âå:΋ŽzÊH×TyÀ{w‰£BÇ=eëí‰xiÎJ&²ÓNH¶ÞE°zЄª”Ú;I¹»³Sº‘ŸrõGRéd'{ÒûaõÊñ«Á‰™™ùÇ$eöcÊä.u51J-.íþ O¹¬¸J|0”^¾ž…·ç™ÛB Ì!‰³³»þ5U‘‘÷ˆ=yOhßôró)üAÂ/™¸·¶®TûÝ>n¶(‹š]àa%ÿu•¸×!¿&¦=Jíþ™„–ôàÎ?…ýŠÛIŸ3•IwÚÏjªš²ÈgoXjÏíõ°ßU?@µv S ¢}*MüÉ/}îzN]¤«/¼Ǭ¨¡^–•﹕wÑTšcî†óÔp¡fà¼0‚݉v¿iôpM 8`mÑr³ $ñ”À¿vÕø´?pµ„KS>_˜Y˜Öhøæ¿øã“&G·\>™š1\‡Å{¹»× ‹n_ë"ynvâ¾<éÀƒ6X§ô–VM\Ñăȫ‰~ÄðÆD‚é‘"²à)%e"ÍE~Wìl0E†p¹g>¯Ç¥\R1ù!Mˆ'g„µlô¨ÍZζ ÇÞØ7ÃEèJRñùð§JÙñà«§¨NÈB¿çko±ßP3m=c–üžƒ:‡`©ŒRuíNaç%xê]Ÿü.ù×,þu¾"Ö]Þ b‡çÛļ?¥ÅÊ8Œž/dâêeå¹A;>¶Ý9O^¿UvÂ4[äEuްòÓòºŒ‡MhPÊIJèòÅOPmÒ6âô¢8Ì ½ªaSˆ¥ë¬Y ,ž2ó¥á0Û§Ç9Hm{W‘¿ñ0ËR¥7è{nºF!ù}…f\^õæÁÓà×a¤Ïƒ‹ ,”?§ƒýúP™¸û zdÑ~¤Aõ DWÏ‹0§‘÷ºv4^˜;Ò´§oAH)fiÒCöù3ÕÞ‡W1ø¦çRåõ V?Öô ŽèK¹¼§ãØ:忈¦»JÙ0W>ó ~hò`ȱU›ÿôöx\𾫞¸yˆ æ¡«KÍ.á)©£äe …é7ÿ$‚uñ°L€‘Mó³M‚yûr- Ð÷ÊFE 5Mé­{QBM׆µìýY¹;]•^¿u… ̉Ì(çrÕI ü¢xà–a¢P—Ý;nXTa­ô°-L(ü„ZÈ~@I±ž¯Ò§ö Ô¸Ñn­±r“Ë•Q{UÅi£³T ¢æÉÃ;fãKx¾àÑ1ðqÜÙøW4ãäOe½ÏßÖå„6~¤³[j朔¸'CVFj~–,Km]„}ª°J”­¹.‡Ú³ýI“uc©g@*¶ºÉ…ÛzD^’ÌA+¼?Yà7Èb×­tn`à›L QNqùóªý 3'µMcÃ<&üá;ÕÀ…ïÑJLjظ5˜ZHnÌ}«Úæ ~Ð\ æÑœ–Na¤kF†2HsЭÂ` z|*—üaöE¬:Šæl¨Ì5¼Ò´UÁ+…Íò¶Fí“&zÔŒé/mb‡–zö*$ 4Uyüco œÈø˜ìÔ˜Eº‹u€W¾ :1Zäþ¤EGâuÛ¦¶´3¬më&V¡Ú›JÇYÁ˜éák)¸…¥£Èh/ý©|C[À¯SxžÀSŸ²ÕKu)|iІû®bÖeÔÒyôÔºP|§ä·F4k—¶WÝìsu߸$lGUt¹ùѦä¦Úå§?ÃÄ)LÀ¶Ó!Y_±{S·¼ó óuÇk*l.ÌáçT1>|Õ! KÖÎŒÇ)Ñ=+Öð¹×tÔ‹ô]þ2¹ÀHýuç‡úìÐDµ97ÀÈô¢ úÞŸ“Èó©•§GgîÚª¥@*êÕ!l1Ü/d*¬@Oâ)ƒÕFº¡¬™6†2çŽûxwGÙ .žÀˆ”"‘߯Ä?Eûh–ùÝí;+Ǫ(•Í!Ö{ˆ€Ú¨mõ )|Þ§ÖóüêU½Ë¬3-ÄÐüØ Ïi}ð1#ƒì>j3óç ¥áƒA3ÒÊ‘s ÞWbUÊU½€‡Lc£ _p?U ð†ä§mˆþÀ(±ÐFkg×$Œ3ŒéÓ¥Ã0®G?îLECÒãÂ( àÃÔÊ6q¤:[¤ð¯ežBåÂ:ºùQy=21h™²áÙ½NÛ<±˸ø—džÄ×¹øŽr&lŽVïä&C‰ŠðšF‡?|íB™Â;aâQü ÃL@yÀÚ¼i@ð¾=2Æ À_wBæbŸau¤¦ 4›è€p¢$LÅí¤ˆ·6K' ÐÑœ`u¦ÕUY²`/sã1/¤Ï ÅLm5iýê#áÜE½Ö`ð®ÁÆèöÃís!Û¹¤”JFoQ¯ìå:‚b¶}-#æ–Œÿz ÝÒ£€²ñX¦ïè²BÎbDæmóf}ûáLF‰ÌåÛ•è¹8bRw øìÛà^ÓAÀ0ö[£§ …‰ãöZ÷ þXS=Q»#3xÄz{©Õž¡¬3--TÌ7”Å"w–•8xnʱ»u{´p³gêôë.IiÔÚ·ã˜}É/T!0WU3‰É/¸‡gæÙ›Ý‹"fФËiêäÙáÁ>>3¹v§&z:GÎzNÔ)/"ÁGcn+º ™§MRnsÔlz2išüN·‡ø)5‹MÁ…uH÷ÈëÍ!ÃвFK}ÆŒ(Â& GŠ¥öŤ$zg[fí~SŽx¾þ’|¯r»÷—‡ QÜ7B“'c®äC%)猂ósã]{ÎG媛`&§UဠV¹ï³®¶=Ô_Üu¹{sǘûl‚½Œºc}ª;c]q)pâµLÄëaËjK«\;cÓ„ÊjµIÊί·Mßûy³mÌ.¶–ÖdÍWÜ+8+(™T’¿c¯¾z¹?W†÷ïbþÞ¼³á°aaÝn@»vìúl_û¥`2Ú|ÊjBn¿(> Ì:~þ©.YŽºd •âV!Ô½ý˜ñS0ß–:AìøÚüù>á‡2F*~÷3}ýp߇þŒ×&}\®Çž\€^j–I¤óÀ¥ýŒ• Ý)ïÍ€æJÅT(ÆwüVŒE×È‚°œ>°Dßœ›é3 çÚÅûóñ³](CãI×Xr}>ˆÌa;™Uº#ß:ÍÉ1¢áQË•sÑÿª/1 dœ<£'œ¤c˜Ò¶É÷â‡amʬ£Š ]hªçÅ'/%u¿ë™êЇ: ;´£§ññ}Op ²w«“æivšK0$+®8V•ääßÉÑŒ¹°–ÅžI<ÁÙ¼ÎTÉ‹òÞöZÝ…³ÊtG…ð¢ÿì P‘'!\ç¢Ù¶y¥þîJ§åîšê*ûÆÕÓwÜGhE¢ª¥@ö¨ïÄvùB•´*å ytG^—zA(ûF¦.Zu¤xÌ?pëeáÝø@¸õ0*í`¶“•Œ žz€]/ç½£8…Œ§NU,fÑ=9Þš`êðýþð‚aW¨á‡8ñû«Vϱ^ò´­O–I—‹{ΧNï²)O52_^pžW”Ža×1séÓv"úù™ª£/`¶pMà¤hµOg¢Ã¹ÚøßíÛÇKV¯5,Š¥„hÜ® mβ5ÿÈüò¬å‡~lý³¤úNõ5ŸÁ)\˜ÿ•±šha’†Þ6!Ɉ °H­÷ØÇ>€ÃvUIÄ!Ø'ºsu =ûj¹|éá>²Fáõ¤T8ÂY jÛên§†áRÌŒç:ýÜ#vîø= ÂòÞ¹;Aìó*Íõ…´dÊɚˑ˜³ìF`Š…e¹R Eû£bv‹þϧÂç´S©ÀÜ[.AIpM+\%œÔ³¨ŒöŠ5€‹¥¢CÅ¥\Œª‘Ù®#ÉOJ›Núë­Yì£zë™^wz”ã~elý®µV¾Q°ï*l¨yÛ1æ£3ij»|éªÆ×B¾}Yü©k’29ºñôM.”GÉjÜØ¶¢Ø=ÄáÓ¤‡ ¶Zîp–Ú½¶T¸ìRñzß.åçç0Јº(òÇäÈC¿W =òå±.d+Ÿ•ï#L{È|Ξâߎ^å ƒhÊÀç`@'¨úÜÜ,>Î.¤_ܣ̵ղ;PÂ}çî‡7»É?gkfœ­ ”£3l¿u¬[ùw¦ñ™Chå2‚=ñÀÝækí"QÝ(n¦ÇóÛ±¨œñÔÿZª#½55´¤<º´ï-Tò î0è&&ÿòT/¼HIwÇF«n3@‹š¶Zøâ>âó[Ø’&¶|~š$Ï…`èD\!äG^ø*T©À MÎD³¦ˆš,/²%)£StprªãÛWý§½[äz5Ž3EY9IdwÒà^oã$z¦ÏÓ;ºJA–…jä(³˜Ó‹ÕF{U %¬ ÿ‡‰cG¾ÒG™žÅº3xàÉÞIX Ø–0±nK?Í”ªñܬãÕVMS¼ì„ÿÌÅôêcî&l"Dí,Èr8šD ÕD¤ KeO-Û¤Ô焊% ÁtB{ø» !ðü_‰gÞ»C}[ØìÔê\Ç/ÏJÀÍlùÝÎê%›ë¥d˜¹R†ò@0¼'-)ÜSãZÞì×H%^røAù¼/1ü¾f‘SV$sŠ¢q—E¾JrçÜî ‹¸#Ó °_hinèØ“cÔ¥d WE¶Ÿ`´•3^zC<\ZÖ€O™™Í¹…}ÐBÂֈŀ·øÊwNó¯v° 9K"ëÍtÙtæÚ¢4þt6ˆ=´`°x*±^pªÞÜee­j7%уaË÷5\%ý½ ª7³ƒ·«SÜ€k²ò~™ZÊóŸî«ËŸ¿3>‡˜•¢L¾&C§z¨Ø¦ÀèNHcy×JÍÑmaì//*«ÙAÙ×Ë.!chW”ž_¼œæ¿z8:UOÚ­ûsËN.EwcYl/J©{¨ó™ °G=ˆ¿×…*Dôpć,JéÁ:ã‘R›8°B­ÅaõE2>þ5’” Áñ4Ùfòãù“Ù¢‰”øÿ#àß«¡Úúo .J#§ŸÅžØ  Ñt•{W _Õ£tîæí"P‡MÈ=÷ýܹØYX.+™×³NÙ)2‡zž¬) ‘h$Qj»1¸ÔGR‹œ¬@^[·C_0/â e‹àT‡­é£Á¦3+¸ýÁÆÛ~7ÝÂRÕ£Ùë%¶ƒ`ÔL1w1! ¼dÈ+ùº¡ø”þ²„¤à âq߉}R܇ŠúLéZú–’Ûô:³˜;5Í62b¸jª”à”µàU»i„䯴¿ü#M㞃GÒ¹;Û'-oËžhufy¶Cº¸p¬WŒÄçï‚C&!·ôØÜRŽŠMRZФà¦JÜy6r)˜ ê(ºw´è²Š´¾~M^¹ÍºƒÈ¶­÷B0*ì‹V\RtŽ[ZNýW'’Ö§j9Àr³ˆ=¡9¨#cá¼nbÉ8(>‡ ŠX´Ÿ·æ˜:Vf%£lkÖÈþ3\ºDºtc'¿¢vU³¡Œ¾‡Tz;VLò¼q2÷‡!šKE0‹ÕV ”¢» ¾,eë1ÙG:¤åˆz¬WL¤r.èÜO¾ù“VÈ̳\&Ž3¥û¯çÉ¢ÆòWÃÒ‘hcø¤ t¸’­ãÈ!ç4^Û%fTcCr4•<\¬A§š£˜´† 7V?E¾ØO`¦Š~$i/ò;K«FÎÍ*&e*Ç™Le't1ß]ÿýWy_ä<ÿ8W¡yÚ_5USn3@#®¥£ ¡v˜Šúáüc«›Ñá©.íSïéý)ðZz+W𨭇3bŽªž„ÜIEJù8¯v©~Ý@H d ¢³© ›œ{`Õû—ð4Ó>…œÐ¿#mª¦=ÿ#pføé–…ø4Ç I5J_ð±&ž#òîÔ*oZP»ƒ¬ :ÿ°V·¦ñDÎùµb?÷:‘$HÙ¼ÎX¥¿Ì:º”Ûµ ‹C€”VޝèÝž D±Îk_VWš¶ëiC ]„äÊÃŒ|‹‚‡VbŒf|FAqÓ–Äž3F¹ÒéÃéýKqJî¾¥T%ßç²À_°¾¿âŽìªÛo© T½M<ùkE+,e¢ó»2œî÷f¯ïôc”ÉH÷…Fø «zëè ü°û…j°Ûà.•ä-Ô@9Ýya:øбúð° #tXÿ…ÁØØ¨ùÖ>š©”í¿1‚Þ±+VrùÌÁTôJ()õŒ¦.$a=%_Ö-¡=Y׈!Ì‘NÏH*µr‚ì8•óï1 ïá×KffO±…èÙ¨˜¶|yU¤DD‘…J»"L/ç€ÌHÈ2ƒ©¸âq²Üµ1EöO×—øi éû쫪[ãð~É(–Ó½Ø\²Š]ÿc­vßÜne‹ƒa]¼‰ú33¯ñ?ƒšM¨¯2_<cìE@#ðQT#õ/GŽL4+D‡’#g½fwÏÉÐï®4{™„öâG3;AB[H`Rúd,CÎ-;Bk,0YeÀã]xð­¯çŸ ”_‰‰ŸÁ‚ÅY±›¥Q#_¦ cY ÜH]”]Ðz+‘ mÎù®2µ&àð*;:¤ç¶ÚFªûª¶-]sô_ßÉ#2¡D×" TŽÁ)‚çܬbÒ½NéZÇõ:ã¦~b¹í;¹vÃ^ÿ¼óu±ãÖ›JƳ;r×\u·UÉ^ºÅÉŽóË7€fÒêÒÃ!ÜE6 Èä&½{áùº¡cPFcMCÛço«Oßœb)âJ÷У~êW‡ ZÊž4Äõ…6Ö—ÇÈ@Ä™Z±›ï~,×µ¹þá+*4ÕYdØ8GS{¼«4?K#ÆÇd?)×V¹ºïM»‰+ÿ¿&±S‘+ŠÛ íúû£o]«ð?ª¨@©ÏÿTe¦þ[’˾†Ç¥`¿ü§3ì¤øÆjÿ†×]éè£Bó_«Øá›å g°·òœø$‘«7qq%ïÌÉ: uSb‚=‚»6‘Ž `å¸ù(!wè$ÚÓu™ÃK¼µ>dÄø¼¸„,†;ÚàŒòiïzu ° {²ƒ#¯ßGŒ‹>+¬”SyÂ~Ú_\ôƦ¨ÆVlÃ"Þ\•«lˆYŽ1úÙ…=°…ni9S>à NßPÁÿiBÀŸlrš.=º4ÔYÍHl½ ü(Ýa³û9E`©“KÊÇk^RZæ´{ ‘¢Ršûwy»Å5ÇÕ}Ï~¿é.¡\BI,펃‹,Ü™txö"ÉmdøVi‡û›MÈÍÊsÚBJ\®X½P•@ì[Œ¯#ÂgN9  dÀÿóH†Á(cÿfqîÊï‹k}Ÿ?^‚v2-Ñloc;*ýâèÈYkZ]L4ÃAÅHöösëöjh&UÛ±Róã¾ủ˜¶¸RqÇDÜ“P=Aï„. ¾›çìi)® ;O³­‚^ú²¥ì©pÆ¥ý_±&4±Í…ù¦°¼ÃÀҦ|ªR‹|Þ š@`´fV›2Qàc/ûüƒÁ¸%|Ð+,"2Ò=½¾›™ÙCÅ4»&^öƒUêßjñÚTˆ®ÎÈíR¤é7“K]x¢`ຠendstream endobj 846 0 obj << /Length1 1547 /Length2 2850 /Length3 0 /Length 3822 /Filter /FlateDecode >> stream xÚT 8”m÷O¤L %…ð(ÃXga„¦ì»ìJ‘3Ï0Œf†!¼!²†BÉ–´(¢†ìymñÒ"{x³UÖ¬…7}i{ÿÿëú¾k®kfÎ9¿sÎý;÷ïÜpIKEm"Í4 Q™Šh%” {ÄÖP(e% ƒÃmÉL øÝƒé 2ªñ B—â™OÏ„€GhTÀÄ› •´ªú€ `P(õï@]ÐÃû‰À%À„F0¸.ÍÓNvqeB}¾ÿY­®~@a-Ðöédž Á3]A¨#Olh2Èôû­çÊdzj ‘,K ïÁP¢Ñ]Ë*,2Ó° Ý$«”s¼¸NM l]ÉŒo‰ÉÂÓArPÈÊ€R¼©D@Ýc3À¤~›}(ëÃÐJèåÖ³W ‘©kÉxæá‰§ú‘©.‰L 3%¦/SÀS‰«@<…Aƒòñ>x2ï ÖŽŽ ´­<Äpƒ@'{2J 2e•#rµ 4f}*Q—æáR™ ØêùôÈtÍݹ~¹îT‹êÿÝ"‘©DÒ* ¢·'ÒŽJöòõÖ1 öÓç2, …RSV@/ô%¸"WØúy‚kAôªâèïIóH 0L¡˜?ïLº7èÿkàw †FD2 8ƒ.d*ìguÈ ’¾ÙÐýÓɾ€ ’@­~~ü; )ŒH£Rü~Â×®©k¢om¬/¿NùGPG‡æ ø+¢EŒ² €Å¨ªêX ð÷*?øç¾æµÄ“×φúYϘJ¢êß(@³ûNÃg]ˆõ¥‘~ï`NƒÔ ˆŸâwDaQè ý?¯ÀZÊÿ§üÕ*ÿUüÿ>‘7…²G|üŸ8ÞƒLñ[G@jöfB›q„íõßÐcà·u>ÉÞÿŽ3ñІhS](?If}A¢%™Ip]SÌ÷k€ªSÈTÐ’Æ ¯¾7€"…úW Z9‚;ô¦0 ËZ ÐFýÞQŸJ WWƒUðt:Þ†‚ô…Áb4´£DÐwMÚR‰JcB)Ä. Ñè°Õ+U? ñ«®5  þb*H—¦*²V=h8?!XIþÅT”Ÿ(ÈZ=þ8$W¤ç/&”ýkT@2šè4~kæoœ Þt:ô¬ÉÈw{ííA_ëj§†º„–}Î×e)·`Txëf¢æ¶Òöyg¢‹[œUΊîÔ®z=½ø÷Ž1Ìí¯EîöB(w§þ€äh ¡®Ge›H΃ /vZc˜ycFL++OœV¦]„¦Š­XsZ­²»¼¦‡Û®0ÄI?øtßuj³ {\iÛÆ– Ñ›÷¨©)oÛZ®}½üÎCíÖׯRŒ­–‰Ëb“k›0Øºî» ä·É¢££¼ž¦s×G'½¯V1=ýh…UëïYŽG„Ì•…#œYÆg«ˆlgŠÆ²½-ö…Ó‹' †ŒžßËÅ ¾Òœ³µ?*çâpqX‰¯ÛLg˃’:†½%ÞQ†;®¨ñâ—Í Ùšû3´Òýí+§eÄ[Ú;ì^ d•ÑÁ;±îÖm‰rÖ¥é¹ÉÌüM1og–:–2<µRM Ùƒ|³ÐâÍÌÏì¯j|›¾Ü‡xå;°ÉùxŠ4%gÿ)3óMò„\þø-ûGŽ­‹a8(ß=-{Ç¥‰ ©í!^zô}rI¬C1§pQyÖ‚èš­FYÕë$$YIÏöÊ-Óf[y ïJIe©\ì™n ¼7Go:Õ[|Þ)·^|Ÿ÷É™7 sœ…̪Æè÷<ÔØ«?UÕ•œ«TÚÖ-òð‰ÉèEħ¤™{)u ÿš}žhøó==<^ቮg¼N¸eïLs,Ôõ~°Ñâeæ`ìWÁ:Ç¿h(dÃâÜA¯œcþ>g­$™‘É«í+/çï×–2E[r0oÑgÃBI)¡^[ƒ:™6}êïù4N,È\{’Óºý%¡_ç]Å‘™‘Ç_ærŽÒçß {oi1KSwöÍEðHÇÒ‹‚Ìâ‚çùüòöfq ^>˜Ê ¶µmÈ|9)‹¼Ñcôt‡þ#á•ðDçi I™=y}½ê®Î/™d ˜ÃË}¼ôм¢áÐ>6n׃Å‹«ÈÅ:ÏÚô`G‰úaíÚ„³SWE.5U¤–’¤û5̰7ÖŽL”ë$éþ9Z¿jÍüRUrHî3ñú0²ÙË‚“”©L­»;Õ92{¨ß”—åÜavŸÂ'$î}¹vÎýs2Íó~Ç®˜ì+`ôå½Á³…Ó´T«{÷3ô†ø€NÉixï5ÝÄWÓ¹DͧÑz‡ŒN< ¶\Ú!q­—«h4jCAöÓ»G8";ÇvZ/ *‡°„ÂðÔXŽ>צ§R\728›ãº²d¢ãöž¹<žög©C·ªð®cÏçi]9ÕéÖ4:4l^tKB‹ˆ]ßeWpO8ˆb§ª°ÌaÝÚ“|Z±*^^b:“–à^ñ=‚¦®«&—b— Ë?íf O-›H^FÖ/|=3Lñº³k™¤ÁµAL7›ë^½¾;¹·QC1º3ï°Ó“2ÿ·qNE7µêíð]BÁ5ï&Ü=‚9†ªiøã@ËH1Y…|=®é„ÍHãcÚ›Y&Í¥žå؇٘Do\†_z –ÄU}?Xõ gÌu­ÙçÒ­åOÝ~•jÄÆR³[ªá[o ÎÁû©_³‡—nmôA”7äÛ™³ÇçD¸Î#ž?jøì¼3~÷UÉÅîš·Áão„z;t?H÷è•—§hÇÞ ¼ÀÀ‰i*PN1koW¾´÷ÎÔdivE"fkª±š»ÿô%â1cŽ‚$š\L]m_ôxÕ‰‡I ·zž“—Íö•¾Á«±íÐ&êSfH«ý5K±=qÜÒt¦­¸»0&.[û0w¢ysZ 5 dž]@LÚÂÍó6=e ˜D¬ôÝ,¼ôôÐç*5Þw –€xÏÞįEد½K^ŠìÁT~~zk“{=ÿç /Ú_7™+õuáz¦ÐÄßj/ >6mÖŠ_LRHÑ`VÌöæ=X”ëÜm7USw°zÃ嬣—Ä|:ø¾èL7ØeÅâØ¿Ó‹Ÿ»¸},ùÓ߆çJÜŠ(¶––mKYÏÿ9÷EÅÃ6현Pñfn\J )ùFŸ³ôÌ)ø©ìθ,«gBaüöh¯àØùˆW¥!'.»Í»:îù(¿Ù«¦i{¡æ± zõxŽ=¯ê²9q)¹ž\aÙ¿v€sç5V¸ïÅÍ}ƒ³ÄHŠÎ’Œª>¾p¦aæêåZhŒ¸õͯ˜¹ÊÂÙ²b%{Íþñ‰±¬2ÙûX€>à¹@I~Låw{¤-Û¾Õ?áU`Œ´EÞŽú{Ø5ü‹–=‰lªä?)KÏ€êåöRûôJïAñÂõñÇ?m’O¬¿¾Gœ5U¹ÿ@÷Ë^ž ‚·EcOí6s^¿ÀÝ7[L¡??WÊí-•dý ã¹:o°Oõ+ìÂÇÎjC·®¸”Žþ=oÆûêˆR©‹Ê>7Þn+Ó.¨Ø%=ÒÏhã9êÐß»"D"¨G8Š\ýû&ªò¬bu[Ðe‚@xÄá;Ÿ§G¬ _ŠäÎt¤_‰‘O& åÌëÞS~¸w2‹d)éäeeºþÏþmC·‚¢{3àéìy.Œ_ÊÉ!˜ƒôõ&9åIpØôq¸r§C ³·ù¥TsÓÌZpRZ™)]ä<8Æ?¡¤¸u¸¤&ÊpÖ[,@è§-Øïtž¨2õÙñRNÁ,}-«OBN†1x†7Ù=ûxàbæ—£Z*ˆÊC—GÑÇ“¦ >ÛmwÓ^ \G îC¦Ý½+œ“ÿ´v“®Ä½”á6G’j^GÞL\LêµkrÌȺ?r)¦8ìÅü¼fíäëá½øð졨ö0Þ˼°²ÁÅÙZùqt•SÛXν”®ÐRǬúûön‰±Ç¹óonLu2MçÙG™•RëùCXuû)ÕϸѮ鞜[·Ø¶K<*œWîª1¾ï¼¸2Ûð×Ü‘SyóÀÆeùl‰Œ¦.©¦WóÁøHüYžÝN¼À¤õá$PtÂJ4*(g6ì]Ö³ì–çñ¥¤4Ù"6. òðô…°1öE+îs•÷]õûi!\²—qÔFRöZø³ÕS1í4¡n×rD{抜¶¼‚¡ïŠA/¦Ö_ÖÐÿé²EÌlY#ç8noVªQ7j·FZäášÉ¡¿d—jÞ”v”àk¼ÚÉ#»ˆ¯2xUÌö6t˜ÁL®X§×ŠOÅOÓQ°¬W>ã|l‹Ž³7OÎxî÷h-}"tÑA(|ƒŽôíD;'¶EÏIS!^*1.Ê(nI9©0ÄÁEt¦sd4L|é`O ÖÝ “m.Õ¸rÀŲ+€¿íÔñíÝæf‘¶¹ o”¸Îr_(aÌjM§‘c®ùÖŸZ†YnåJë8À­Þr¦Jó‘÷N,¯L½î™¶üO*ìÛåOnDÙ)…|w9&£Æš¥þæ$“Ê endstream endobj 848 0 obj << /Length1 1750 /Length2 4722 /Length3 0 /Length 5790 /Filter /FlateDecode >> stream xÚt<ÔüFȨÐBñADÆ ##²e†lÂ9‡ãÜqwö¨¬l"›² _»d¯l²G$«l²;£ô»Æ÷›ï÷ÿ<~¿Ç=w÷|­÷óù~½^o.v­»²VK„€‚%y ]]1 ƒ¡Ô\\ºH< ñÛLÍ¥Àâ´Ä±y,†'Ú`xbœ ¨:£ˆ•€Üƒ(,þw +(À\V€†  ŠA#pÔ\òGw,ÒÆO<æï¿œ€ˆ‹ßàÿ™È: °H8 hÀð¶â‰p ¸‹#x÷•à¹i‹Ç;J€@®®®‚0œ k#Í˸"ñ¶€‡Àº ¬€‚M˜â—2Aj.@׉ûe¿‹±Æ»Â°€h@!á4Ž˜áŒ¶B`âáÀ]uàŽ#ý+XýW?ðûnˆ äŸr¿³B¢&ÃàpŒƒ# íŽDÛÖH¸£¤.ˆwÃó0´Õ@ ‡!æÃ\`HÌ’ð“9 P’Õ`D¿åáàX¤#'ˆC¢~Hý(C¼eE´•<ÆÁÆã¨ðS@bpâµ»ƒ~uÖqE{þÖH´•õVÎŽ =4ÒÉ¡¢ð;„h¢þc³Aà0,&N n úQ^×ÝñÓ ùa&*ðötÄ8ÖDo¤5‚øC퉃¹ <ÖáíyÜñoD VH8°DØ ÑÔªÍë_˜Ø|,Ò 0g€|þùw8^V4ÊýOøÏþ‚TäîjëðýRüONãx ˆP!( ",ˆŠ‹Þÿ.òü¿¥ÿ´jÁ¿©ÿÔSA[cñ_ ˆW÷· —ßCÁó{axŸ ‰!N2àù3ø¦`0œøù?ÿÏ”ÿßÔÿ¨ò¿ þ )9£P?Ýltɸ0áE-•ÓÆ°Á%™†J«²‚îð;i-39Ê^r0K[÷E (yøX7ôbr½³ãkX)¿ÀŽJ G0eÙÆWÒ†gòƒ §Á£Ñ.¦Ñɦ?)G›qzblÊÉ"¹vŸÚ ›rSÅ„½Ô‚“Þ4*"; ÍÉ …¼ñ5½u_yªHË¥ú{œ?rRÕXL¥œ'¿‰Gç3ó·ˆ\c‰o@ùO?9»;JßÅ[ÍÑ‹(v©Ül¡þÜ…u¬Ͱ!ƒ^5ï[bH¯ê-»2àãµ>,Y‹ÎC¯‹i÷%‚b-%ò•¤: ǘNÜ;l‘\Z¼-@cÞ»[iXÏNfŠÑ‘qG’Yç‘eJª—ò>¾\n‹ŸçéL{£S¯FH[îßm×h8í‰Ï9‰×¹~;ÚË·.²‚ß-¾ •x~Tq¶vŒ®Ýz%¨rMëëÇ7ŸYNƒèíÞ¡³,5¼Ÿ›®ÊmŒ¬áKŸßФýÂ&h±æ" ~¯éÔ¥þW÷™1’æU®BßHüGƒGø¹æ"þ•”ѶMšP^ÉYËö•êÝ]nõŠÏÞš)#¥—¶”W§J%L^ÞäÙF‰:Qì*3Ç8Ó‘—p)úÈ„‡Ú¼dÝØë !é9ò'˜ ÔZL"Z.{™–Ø3C>oÛ>&¶NC<"jD}7¤™xÏÌUû×™aÊÝ0–9$ÕF´){…É:d ¸¢.O¢pÃ5 ÖÝIã­|^åÔsVMÇK›Dò½^ÎÄÖ t"Î!£ÖïqŠÛ½^’9[ë³¾J}ÕkÂæ>èWÞ'iÉôW•²œ5$+KM*syyDÙÉÌàùà‰[’/_®O8ŒÍË}Ùf ñ/Yì»ùË™é7/’÷Å´mä›ì«¨Ó= G<6 ‚3š?°W—È[€?Gún¯kÕÛ¤#íÞ÷ŽÈâ&[ú2„ ³7«^>>|hšöL›1T%Uú2ÐVvŠ„Ê½_kÓ5#Ä\'Aø©¢«K-ìl½áÜ'•äSo#¬3¿ªíÖw²ŸÊ±‡±Ñ¢}<çz”oD'%xL5éá¹â$sŽ.?¿Ç›qPο}ÁäìÑÐ7RˆN™¼/ssN' ™‚È&dž®²÷ç4㕨‹ëtí1¦#dþܾ~sÊËÅœCSõ‚ÜL³-B$º½9BÌi±=Jôø‰»bY_Ø_§^ª’—^@70½ÈOÁ\o!~h~˃æ&_n~Q^Œ K³™Na¡¥\A7ÑŠà5Nwf.:N“‰—Åípü¤ÓþmŽ{‹Ù‡yqQ’õamã‡Ïçl›@´1ç•{©¶‚Ét°çè¿-ÏsŽõÉæIÕ'¡,:ñæFL½.¾è¥ÛÍ‹ t!ˆ)^§púy£+ŸZ-ÐÉÆ°|SÔ<œÒL¡auÙ(xÃ-†Ê †¬ÚRÊ ‹;yɽaÅ3˜Ë\÷‰.””›Suͼzü‰JnUá†GH1í³yùVœ[ÑáŽb½7͈ýZpÎÊ¢-¡ÂÌ,. 'òaV=“ÌÔ’ ÒþÙ±±<o]¿œÎ’ûÚ|úLÝÛ÷ñSŽR#3XÎEã§¹š§lÒúëÖhª·'7ÖèÛOä’ Ik”¸=übe1¦ £„1ÑÈ*mcÙÝÄ vú¦5yÙsLQyuIW»ÞÜ“5Ö”‚‚Å.««¿²<šÒÞ¼»Ù¡(OÐ%Öåã©!‡i㥕±aÎK!ï@²%ó*?íVˆ³ækª~)í˜\^Ëo—lOVIò ßÜg4c¨4³|µ2p–š_—¢†5·§åÿ”1¡=`ÕŽiÊöAù‚U«CЊuñ=pa©È¶4ÇÅÐÇ…4_Os„Q×îÛd’)¼&p†ÖÏèx R®¸<'·†ÓÄf¹3¢N¼¿ºë”^Ý3%fͬI}Æþí€Æ+}æBàÙ®wcÿ×VCX¿Ñ©rA÷Š,ýæòëÑþ¨šÄ²‡Q(Ã6ž^%Cº^…û!%d#KøÐçµ!jKb+çX¼êOœ…®oX¸5Z1NîJLÊÎŽ«ßÖê­åD—ê#&6\ÕvfG¯ð™M¿ÙH ÿØøE÷·y¢^¸$i'¼h¤òÜò_7NÍÛzåŸ4öe4ìÝۄ£K¥ûN1U]2…¶¥zÇSw®¬î“–p ¼p‰d"Ÿ’íO,US!S¾¹ÏfŠ›Xùì<§1Iò-ËÝž°o¨8WQÄ~òq¶„xµçeù n»‚B‘ÆEÒárÂSƒ·o ÓLeY6Ïß¹ÖX¤—BÏ@õ0k¾…+Ûòž£]-‰Yhú€ÅnÊÛþÙäù"ÁØÑõ-dü™“Q:sd²Á²Š©’‘Yáçî×u06ذ H 6° \J¹Îá@8IíP ´\×K2Z¶L§±JkȰÅ+ŠÖ8þ|M®|íö‹uÊ"[² Ì2U-¨ììxF§ï%ÜR‹|æ€aOr›Iå¦é6QÜj¦—`£<¿•‹W\Ghoȯ „“sqƒŽ2œnhlÑP¿š¦7×{(Íݦ|kZlí,Ò†EËó²6žÀëÒ "é'ì^ß í[µ’—pþë¢ÑrÔ)Ñ,šÔCt?Ìéíxš‡J‘° ÷f› ±ñùiï~–‘´>µ/N^líj“)îÍÊjü+䔓‡‚+S%2åû»Éîû»´Æ{¯SÈÊší“éÂF2>õKÈe§%Æ<ŠHT‰ÓÆeœ5¥2¬.³xW- &9³+ÔFŒ’SÈÚ®¨±–. Ùª“FC¾PŠMN¸˜_ylzrªói…ô)ä‚“i]©A½Y—à÷6¢Â_v4†’¸Æ°MÝHCvÃÙ×¹d㺵¶Òþ¢òÏ^,ëbôÑô6Äg¿ôCz·”¬pý%J=“w£ýÞ+„—žÚ©ÔïÉ1"è®?öš–{7µ(X¢¨ð,èÈ?ýòÅz•¾­ÖÁð@}ü#mhûÀúU×È Ö<ª’@Ç)1†Ü·„%©ˆðg±^„#SžðT»ôo†»·µ|åyæ|6¤Ûp~(\Å~kòi´â Îõ‰ÓÊ/Ès”ÈÎwDè$û9Fœ¡L_ jKf"ÅPîÝ%Ï}¦×  :ïÿBÛ Oñç³üÄLîY‰¥×Ê ±=·g7œ‘»R¿{þ$†J÷\AàµNBFáTÿÌ=wgÊìû€W3 \ÅŽºrŠ×ã;—È ž“ ¡m³ñ=5*Ó¦¯|HÒò.ƒÂ‹—‰Æ‹ æËšY—a^èûy”L3:à,— yG¿<¯r‘ìÇÈ®«ë9J>Õ{(p÷jÕª(F±ÍN³Žê…•Sd¿Fº­r¸ÎO4™—E\Ÿ@Ïùo¶§6¬5`¿ô‹{·•Ë‹;*˜)ʬ®Ö]*°1/6ñöª8E—q#KêãðÖŒSÖ™ƒ&¥¦H]eŒ}®z°É>ýÃR5—|ö¢ôX+üûɻͬòH…æ ס«YãÌÍó¤vŒŸ )SZap7ÞËÆÚcÃå«[’El©ÙâÊoXÄDa3ª6oŒ¹%ŸNÊø_(!ýÒ®¯ûqÄ DHÙ„@iò€KÀv™}Ò7õŒIM„¾ñníë­Ÿ‘Ñ/l¥Îs¡õ‡¯b?ÇîÕ ø°dŸ¼kf§÷f‘…TYDA3oŒ¹+=Ýcµ®¿Ö@¿WM÷ë­eeË6J,'ðoÔ¾qŽs$}Ÿºd\•ÙTªlÃjœ0&:9Ê‹9½#6u+¼]gFay‡'²Sµ«N'®öÁ ¸í¼êÜNÝíkAûíü¹ûRiãöÙœv—¨»-ã?ä†IF_hÚq܉¡õÝsF'”—¨o JU][¶ùV³×§{ã2uƒËÂýÎ_\½ª+Mzo>>ˆµ=vX?•"^±ç¡Î ŠŽ2=†g2ií·eIå…íYCVBÊìÖÒ®ëlµ7 50ŒÎ¨\DÏŽÝ|t­~åÉòj”õR¨ÞëþÐ=­âý7+«ágLÑ…ÇÖvÑ$¥$¤ðä/ë—¯—WÜe„¶[`yÒ;&ÃÞ{|Ó훑¬.ªÇò7ŸÎŒ>{²¾†Á¢¢JV¶ô7% 3¡ôžš?ýxJ]äF¥™ünj¸p謕…v²¨èuä ”žÂá£þÒp“0§ê:*—£Ê{&¾p"/´øFQ«L´j²T¾Vï{ißäÀîfÂÞ"[Ñ[¹Ž{âÅÃT•Úùü)~O!°úõ9!áª+/0êªkÁnG·Õl%åú³¦ÂÚ[³·»a¦ª·†ý¸cÉ¡‡*ýe&VTXlx®BÀúYà[įäC°kµԼuk³*gÀÍQÐË;¼è¬KœÍ4z5’n3}45òé'•Ýew¹2žô\úÎJ0lø4}Aax/ ÚÜùp)ئ¿~5êÒ¥zJæÁÅEó}%Ó´a…šî$ƒ¢ ×Ös¹IÃÃKhï«Þ¼*8pÛqúƒ·dx¶…ßËy)üÒZ8ëaßeU 쵈ñ)¼xÔ~f@_ \£UµL¾äÐÎöÝÞýW÷ìöç;!àâ y.g_ÎyåêõWY£Ü]]¾fIþȽ2ôYÙ íÆ!©}‡,AËä}UÙþ" +‚zé-åÅ¡GAñ}%'¢!à¥Zé”dTjÛ®‹à4î*vÒÀ^*Åæäƒ>¶$½m=ùïŠÂ—sø8¯X‹>h›PÞ¢·üàO9-©™E àÀLf9ÞjÊyo3L£^L@CØ‹ÜH…œ^~jG,Ûíßß:*-’q·ä´y±‡Õ×/Ñ—þLûø(®æÓËÌyß…í“z©/‡KÚTÐwTʤš¾7æBƒ—ö£Ó.^»ZOùýh‰»›/œt†=ƒF>"»R•âÑ¥;ôpùRíjÌEPpš§Ç½ºúVª–ê³›Öq5Š˜äÐÔ+Ê'©Õ¸]×ø ‰g¼Ö aô·ü–{™‹Ê,~FÀe1ÄA|ôDÕ::æ¤Òö_ÙvþÝÛšËW™ö7 ö –«̽¯ÅA5&[I»Z ¼Bc¾e†´bÞ™V5׆¹&›]û€³²»Î&!$ííË|’XQ¡<}“–húW“š©øÀPèÂçÒ2¾‡;Å šTk wF™[Í]G,Ü ’¡YR;þU¬*ï®ÞËŽrZã÷)¼RÙþâÚ®©—pOwzt¹µ|ÂÙ‚G›½S#­ÅaçØú$ÄX$´Š‡Î-uüÎ#Jú~9×¶‰Ã¨ÈBûõi÷>žnUkÂý³²f»až‚ï<éÆtÐØÝô3ùÁ+½Fg½6åLo£ãw»Ff’ ß2ºßh‚ê»ÿ|“´ endstream endobj 794 0 obj << /Type /ObjStm /N 100 /First 956 /Length 4711 /Filter /FlateDecode >> stream xÚíŒ!Ï£B(RSÉtiT2©Þ‚·©e¢dh•¹Ì4!Î,æ=íÓzÏ*<ƨ,VÛR±Ÿ÷XeI©Ucù–âyÞ8ñz宣q ]ŒPi"Í€6È#¯Dˆ¬˜Ä§„zøõ&¾!Ú.Äk$ª.Ù +ZŒR´“׬b,&¦…»yVî²±òHK Ñ´g\wº±Ÿ Ýž"ŸÖ¢ÁòÈ+Ì]T”™/0F0Uç`4¯DçKs ú") d’(1ŸˆuI¸%‚½cþÃ<‡RGFÜѼ˜°R‘–ù4’ŸÜó!WÎ5ÚdÝä9$aUh“WKCõÞ®°.2d»›w@1Ž9ÐÑHº)ß²¬xÎ#‚¬Úí“·EŒÅ(ÑÐhölõð-ÛÔÈÉÏ,T¾Päci¢H#4æ‘,+b‰;4éŒ)8EÚU” SÐd?¤¡LwÒ˜åøb…5Zʵ”Jɯ ÎHoíS–w»VÂà*kŽ5”-§ áÓªÕX¶Ó@C׃Q„œÍ’=>ûÛá˃s%áÅlòiQYÞqppóµúýóÕÉBy‹iâ=ñpqQ_/A°óprû´ž~ú Ñï $ƒï(|y¼œÌ¦¯?Íê пYÖW¿b¸Üç¢7àø<™¿©—Õÿˆ‡â@ŠGâH<OÄSq,ž‹â¥øE¼'âµx#ÎÄ[ñ«x'ÎÅ{1Ä…¸¸™Ý\‹KQ B)꯳ɕø(>¿)üûR‹7wsñI|Ÿ¿Ý~®¯ÅTüŸøSÌÄ•¸×ÓëZ܈oÅm=ŸÞ\йXˆEýv.¦_ÅR,?ÏëZ,ÿy#îÄñOñU|ÿÿªç7ÿËÂz<!*T²z½÷l%ü£7oO}ÄÂ×#Â7(|…wÒéç_¦„¢_üo­à¯®&kÿo–ºÝEê/_¼?;{LR#BOÙâµq?GèZ ½ÏŠß…•wG‡ÇGGÄÊÙñ˜ÿê–›€þkïËÍtÛÆˆÂ(?0‡ÏYÇ Ðá·>qþ~==xöþø;|s8Âèž¹“!ôuåÔ€;Óq'GJ=Uòõ8»cÿ|ÝŠ»WZ6\‰ggG'çïáÈ/Q!Û0Ù‡X«B£&mì3 %“ôتP;9ªBä´cî|ü¼¼ôëšTØúæ_äKöÁ>÷mÐïß¿}||μ譸ïC¬ç^5Ükÿ“¸÷®Ç}Ÿ³‹‰ž¿:88zLçëßœ^õ`b¶t¿¨F­t*®úÌ´¡Q¼>z'}½¥aöÖ²fe£™~D3­ÿù´9=ë•§+f¦ÉÅݲ“+°ÛÅäúRLK°àÅŸ`Úæ“‹?ëå¬þ¸læsÊ\`óÓùÅÝÕÇYý5×Mr»œÖóz1]tYîêr²ø,êkþøën2ë—”ýrœ59ðÓ|ò¥Þ&Næõ5f|<`%׸âíìnþø×]½XNá¨ÝÝ,ëË3k’žxÊÉõjÊìuiv1C>¶N¶z§ uôËùÉ‹'dCcÞm¹ÂI1þˆ{ÈÒµGœãª™I¯rùÈŠÂ"e º`5Ì{âXAhêùûw/ža+ôÖ Ä°Sá¼› Ÿ²©çSø¸…O9Ó÷©cð˜2I¯$³´‹‚OÎ_>}Šüø‘ò£‰*™Ÿ¢`Ü6¢à‡EÙ‰z¤*²ÑcI#‹¸øèÕÙ[ä l»ýë9 ÇZÿ”¨Ò&&)ô8]µXÓ¥èßΟ‘ÂâVì–û×Û«o+0ùsØõ}v9táÿ¤ô×·"]òé‚.Õ=ƒZ4&ã¤Ù©Œ8zùèô·ò›cÉÖëÖ¬~È‘¤Ò®F<éòf6›Ìû íÔeœ¾;<{Ž ½ßÔ˜$ )¼ãp£†³}edå(Gî ?.)ÏÏê‹›Ûoó%$åzÊå~5½¾[ô9nSxõðý‹Ócbg»(ÑX_:`[{Ì~!ê‚ý¨{~ƒ-û2Î~/PCâæ¶¾Î¼ßΧWuŸÃÚ±§ç/=ÅNe¼Ù„†¹1Rû“ª]7ÄûÕqÝm_Yt%á‡a ЯÚFBÆà²¢­ÂF‹¯&^´Ötv¹E…eÚ,Þ==9~sÆß®ŸêClØx§$ÍN{Üð¼é·ÊX[ÜZ«v±µ×Ïß>$>â÷L-ÉŸdjÁl¨Ÿ€IMz×X26¦q›Ûã~-ewº|zvüÛ1^çœv\À³Á?ß À¥/XVªÇ2>všÃë§Ñ~kkßz>¸äز½‚ŽŠmýÃdN VݶZ9…nêÀúm% ®é´YÅíbâ¥Ï¢ÇÎêÅâç¶WƒëÉu}ÓÝõ%„˜‹›y½ÉÁíN™ôðÙÑëÆ*ôøþÿ®=¹·Šñ ‡NäÓFηk®úìNâñ£ƒ7§¯‰Ë±[YdRÓ·^|J?Ì$V™£Lö­ð1·‡Þ^ÞXgC¸c÷…0’`áw–ôˆ‹@þ`²¨ñÍêïdz2£ï„!Jñx:_,ñÐrübÒ< Ç聯ËÏ úŠÚÎ䇿•’w+äõ(ù´;ùÁõüzRGcm©ãC&’Ùøê…ú~ÒO¡Ç½*pá¯Üxèk5¤zÊÇK…Vú÷Àð2ºO¿Y8 ïâ¨òÝîä·©CæWMO–Ú§ßmµäí=L¿ã9`>ߥŽ;^)û{øýà®lÈ|RÇß»š÷u%w§>¸˜êSǯ‚íΌٺ‡Ý÷¯‘¬›£ÇFgÓãß³ÞCëå…ÎÐâW·fŒ¶ßvÿve@Û˜­C-~=ywÆ—C±¯¸›ñyã ê÷ûð†`H}%ÒË‚x/ÎÞÃ×íùÐÓ7Ò¶± v§=l£Œ[ù0S8ºÔ»“tVCêfs„/¿+¿;óƒgH~ÕæzqF—þîS[õ‹é!ùÕòBަ÷{È~P婯dWëG©¯É®'“Oõ Ù›;,‹÷àyŽE0þñá}>½\T¿þ#üf#ò%þ8:•?‰Ä÷¢á2nïø3xþŒLÛrqŸéÞ4,ׂ¢%úüùü6eZì£÷¢á¸ŠÀo\äO–•ãß‚á÷ò§¿? ¾$€Æ†Ïï²ü7ù3ÓŒòþ4bÆÁ²À¯Nð'W ð™×õN:W% Ïi¿ÁŸŽiú̇™f4ߣáFiD¶+ÏæOßñ¦Ov*ÄïêÚ” èžÑrاÿu GgÅȬNô¿-|‡FìõD¼ÍRJß•‚ PÖf#Ы»ålzp8ª\¦bÜ ÿÓžò¹l :]Bjr¥(ÂÎûÚsçLp2¯¿ÐÿQƆÎA› Ð:÷bâ—úkw¦.ÝàÒ¹–ipµÐWX…Ö¹ h·:ÓVë m­6ñSW™¬Úƒ5‚W¥àè!ÉVð:†$]ARšZÆ}‡k“ð8 \1­ÃÕ©! Ôд_|®°N ¡SCp¡Mï$ë”:¥µ —/•2r®NÚ>lÄÕ“vX'mßIÛ›¸T‰Ë¯“¶ï¤í6JÛ…®5Ψ]'{·Qö®'{¿Nö®“½Û({Û“½['{×ÉÞn”½íÉÞ­“½ído7ÊÞödo×ÉÞv²7eoz²·­ìÿLM4 endstream endobj 854 0 obj << /Type /ObjStm /N 100 /First 866 /Length 2788 /Filter /FlateDecode >> stream xÚZM¯· Ý¿_1ËÜqô- ¸qƒ-‚¢í®ÈÂM^‚Ô°Ÿ‹üüòhf®D‰#{áwçR"yxH‘3sí|ÞÌæ¼ßrÚœ+›Ž?ãælàO»yËr›7Ÿ‰?ý"ËMÙ¢g5·dxݘ-%z°%m™üf‹Û(ÄÍm…mX [œÌfM¡Í²3kËn³Îó·ÄR‡¥6ë Ár´áÁF^ŽÐ`h6áO€ ÇB€Qþ ¼ñØ*÷x|™­¸eƒŽ‘Û°CwÙ>XÄæï±¼9pTÖðæÈ-u086— Çæ2óı9âÀ96GŒŠcsŇ{⋼5̧ãÏ6Ì;&ƒãò “MyÏrŽÊ&…ãñ1Øcò‰qpH>±œ#ò9†È'„ãñ¼¯¤Ìxy‹gf Ђ6áXN[@h¼+ðÅÈÙ=û )z–ð"q¼ykI…/8­¡0ÆÈÁñ…Ýbð¼”Ü#ÒšqØÃ!PÁA(”88”1ºä#´hK±n.[BÂ(s¥.#ÊvËê̯°åÌœ¶ALNNÑòED9…‡J³±ØÌÿœÁf¶å ››cBòÙ/kÀF‹ef‰Ùä 1 ÔaŒØ·’“} 6Q ƒ"ŽÖ6qb9ûþ ´¥.“@…Ë™/჋ÌZ¶ÄÞPAÕ/WŽõõŠë̆\¾ýöá›==ÿ÷qCVÌö‡o^òeÜ/ÿþúÃãÛçzâöïÿWcýöããï¼Æ!àÛwß [¡Ù²+[|¦;[õ¸O¶Ìݖ˺­CÛ+Ú.5m/´q–;$æpóÃÓ‡Ï Øß^ãA|ÿîk~Íç~ðâî^l‘O»»«Ehó6.µóNcÞ6æ­]Ù2‚yWcÞä¥-‘«åÁ´<§ÛÚµ\ƒ¶=µm¡EÑË{†¢Èé sÏ©“9Ò¥-¹¹ Ò% —ÅÍ€mñMÛ¬´‰:ÀQ³-*w[”t[‡¶†„bÓv+ê‰4ˆãp‡Y©;ažÔùÑeËV³E½Ë¬…›ñ9,µ]<ÍVKC6º­][E’ñ)éÔ¾ƒ ë¶“u»"+µü$™о×§>?$JûÍQÚQ¸ £Ë–Ÿ8äçt²»Œ+±å'†¥¶ÈOÒò[~¢YÙ "[*®Ð²ÒÒ–È]ÔMhI ni«ï]'ÊÁVcÛ_°}hEÛ7¶}X•‡•lˊغ(„6™‡Áœúû9m¶©< e©Ù3®Mä6‡y,̈٬¡i“yÌÒLÏ~VØo³w½‚老“6B‡ :aÁ‡èÉ'¸š¶áaÈZ›¸ãÀí—6ÈÚ|Çk¯)†«6[Ûh'«0ÓÓ­¡iSuªÂLϽ6QÛ@çioFÌVm´¶Éê¬ú>ƒA©è6-ý‚b×SìŠÛØt ŠÅÌÔFf›˜nA±—Ú´ì†å‚b1)ÕAÙæ¤Nññ¬¡Ý÷´)³šWý1•O,ýxŒòyÅÚa Ü»À•˜ŒÚQ»Öì- ×ûñõ›ÇÛ¿¿zõîç¯ÿùüúÃó­¾ÏäÛWþõÝ»ç·ïž_ØÞÄRÇÒ½ƒöRãÃáFi¸qߘöÆ÷Ίõ'fééÍÓó€EìýiÝÓ{¹ßÍÿåùñ ǽeuA逘L'`tqŸ=:áôÜ8A«ò¡³˜!ˆ€ 8è~ýþýãÛ_ž~ñòÆ•ãáo|H üBž¾û}ÀûÚ+¶QÜ`øO7¼ª„?@xPøëÓoŸ>ÔÂΑƒÈî¢÷¯Û‹g¥ÔƒìýŸû&»Ü°3ô]·&÷xµÂk­ÃÒK8Á!¸^Âûï¡Ý½Þw]cŽñ~º3È E@%HŒÂ97©“àù»cßÑzWºµ]:.‡â?³²KPýŽz Êß÷d8Ô¿{pBCE0x½ïº†ú=a Å^zrÞ£ùè¡»GÄûÝóŒ+ßÚ.—="Iž&Ӈd…St/QažéI®¯KÏΓ×3 ¯÷]À˜žzz|AËìÙ §/§`°¥W LOÊ}4}'Š:.ºµ]:®zJ_²ô”>ôÑ“{ºtZLO¦žBVòQç NÏM:¬å›÷©wHô;Ê­þnW~~z÷öµcg£ N{P¡áLö'xm­«ÄÑ6 ИQŠ3jì(Å9“œÕ˜F)Îë<`±{g7Mê› Ö3<XÛ\…8Ë9RœçL׸óMî¾Æ][ßÙ¤›ÔÒÔÒHmmƒ4F^[a#¯nŸ¦*p »ÀAm™€ãüO•‚éGÜh“ÉLRô3Fƒ^”ö‰ªã¦›Ü}{oã‘ÚÛçÍÞBÇ4Ô6j'àh¥nŠÒ]W8ÐˆÝ à ÖU‹öêGºj‹uc4µÍº1òÚj]¥`ɇkÜå&w_ã®­wÊ>ÚošƒZ?·P§ÔÔú 8X æ8ЈÝ×Àq÷F#¨ #îjÈ;‚Ú0⎠6Œ¸#XŠ×¸ãMn^À³q<ùÌÆ±z"˜SŒ`6ŽeÁìÔØq®ë$ Ü«žêmÁHl±i¤0Ø4R˜@lž‚Ø<ÙIùº¡Ø½f§À,í Ys“ÀìÔÁq¯žG,Ñ·õy5ê³ÅíÎXx˜fPî¬7!RÂI‘'}ß^÷¾ÜM÷פ>øÊ\ã4 3…hÍà?ÿ Ú{7úôŸ»4?vÆÝ3^±^Ÿ‘47õÑ_Y`úλu!gï­¼—3¤ó^^Èq‹:“>buÖÑÔ;WÅn`5̨" s-¤IÀ}òŠçrwÓµ¿ p‚‹ËÐ òúÔÓM×¾øëÓ/¬IǽéxAFÇ!tôOš}ö¿ÃLoœëÇÛ5Ú»®ÿùyÿ Ççá=¥ë—Æê›³Óþö¨t:Jè¸q§£Rv_ø’«”>|äóñ†”Ž&JÇù ãõ-^HõO½/êãy…Ž':^bÓ1‘ˆÂÞßGãÿx)4ä endstream endobj 901 0 obj << /Author()/Title()/Subject()/Creator(LaTeX with hyperref package)/Producer(pdfTeX-1.40.13)/Keywords() /CreationDate (D:20130315223655+09'00') /ModDate (D:20130315223655+09'00') /Trapped /False /PTEX.Fullbanner (This is pdfTeX, Version 3.1415926-2.4-1.40.13 (TeX Live 2012/Debian) kpathsea version 6.1.0) >> endobj 897 0 obj << /Type /ObjStm /N 4 /First 30 /Length 211 /Filter /FlateDecode >> stream xÚ…;Â0 „÷ü 0Ð4-[BHl<ÅcB ¢*´ˆ„Oš¦&¦O>}g¤ b@BB8$bǤÈF#Ægúbà€8p¾ fÃ@ ¤†×<2>×7mÝfÇ <64BA9FA215C74513515118330A93A475>] /Length 2168 /Filter /FlateDecode >> stream xÚ%˜Yh׆ç›_ÿ/[²¬]²F›emÖnÙ–mm¶VËZ¼hûeY»ÔRB(„f(¤W 4¡PRê$´…†$…Ò^µpr“«RC[8%ÄRº¦ô"-¥¹( SR(î<¯oÍ÷ž™Ñüç{¿s¾™ ‚'a„Aiú'ð#aÉ ÑFц 3 míaäÐæÐ®‚h·Ð®žEhóhC„ÅàÚ]´Ë„%à4Ú=´K„¥  mí"a9¨@Ë£ V‚*´ ´ „Õ m m€°œAÛFë'¬ÚZa=h@;@ë%lMh‡h=„Íàl:ñI´nÂp­­‹°´¡Õ£'lh h„Ây´F´BÝ íš.Ó?ïEkEk#Ôƒ÷£µ¡é_êG_@»„vŽPvM¹Ôãj²/£í¡%T¢Ò Z¢é§*É×Ð2hÌF(ƒŒ ¢išFÁÚ 4f2×ÑN£iŠo€ ´:4²N‚)4ÍÒ3 fКÐÈ`8 n¢5£)µsàZ;ÙçÁZšl±–ÐzÐpNxÜAëE“¥î‚{hš?\.ƒ´Ëh²ã*XCSÍàØpäÑ&Ðdå pm ·‡›àÚM4•ÁØF»F¥„;`íšJh죩f¨²ð¢©fT~GØ6-ö£nj>Ùd@eJ±ûmúõ»/@ÛGS‰Sì>‡&ó+ÔÉé]ÂU™AËÿÍ¡)ñºOêO¡¡iiáWúÓh§ÐôÌ/C+AÓ²Äìú ´t4éw_…V…vHHV} Z sàq„?ƒvmŸ7ù-Bcþd¤= Ö¥aôhŽõÏæÓryf‚r‰5uzf–ª·GSfÙ×5JUÄ… d-xá«8aÁ·þšÞå]…g@±¯v*¬˜?ÒþQð}¤e½œ¶àásé ^ÿRÀË\ÔÃ@9¨  TZðÒôäïæt{Ý´ Ô¥Úÿ¤E@;N³?ü¯´ ï¦Óþ³?§7xô†´tZðÞ³ µ‰ eŸ56>ÏQ#Gzæ.Â.Žô2?[[¤ ­£vŽ@?a›¼–þËǃú,æñ¿;üóM]Æzk—'-øü‘ŽÐ´˜›Ù«oëè$Èš•~AaŽ8oÖöJ`ÖU) _%EfM*,Åà”Y÷Ò0fRfÖ1­›%.ÁkI%Àp 3™ÔšõþD瑊×%õfC¿’Öh…ò–àƒ¤ÅlìSÒ¦D—8ê} Ël~T£²¶m¬—ô›­miû$d54Ûø†4yRýÁP×r¨WêPÔ’LƒëfoéÚ@ý†6õ³gŸຄE!QGA¦=éNÔ=`‹G$¤6Y5{þs]«^@›?ùM´å?`iÖè¶Ù‹ :Ú{€Ä'GüŽE³'Ïœœi~_ûHa @9È™}ïS ‚“ h_ÕFª]­Âìt^%¨µ hSj4ûÑ¢=¯´€V ½¬tšýô3§}« ô€k ÍÑûŸhth+bïY½ØqV‡À ú]âè&6ûE¨kGÀ(ãà:¸&À$˜Ó`Ü‹`Îìñ;ºÕ8`¯Í€ÀÂìËŒ:³ðÊŸ´¬ó,. ,¬~_£$ÞÑZ9ú&Whaû×5@’Iv$Ù•2íp„£Qr$ÙÑ92íhŠév´BŽœ; W0ˆk$Þ‘xG‹ãȾ£±qXÀa×ð‹ëXÀaGÃâð£MqXÅÑœ8|àðjD0ƒSûév¤Û‘nGºnr%ö|¨_ÜUÀŒ;|àðÃ8|àð›XÊÍláðÃ8\ç4íwÀ]pà‡~qkG8,ఀà 8ÊÙ‘}Gö¦q»€œ»a ®§ÇN8*ñÀrS‰²o@ †ÚŠZ½y£Šè¤#Þ/#õkÅ@ƒÚ^¦"5Çe ÜÂÉoêÎ>|¬£J ÿ𜎪,üO³Žª-S÷ŽŽj,3rXæ‹_Nq\"­Þ2ßXA.«°É ÆÒp¥Sa‹|¥6 ¿]˜â·¯Hë°‚Ïé¨Ó²eo–íRØmÙ—kÒðÝ…}–ýõSß÷[®ák:°\Ï_tt¨¯S[« ]¶Ü:;S&¯w+ºÍü8`?ϳ‹çõ‚¥7ª) ÷Ú@×k•¾Q裄¾B,€E°ô–¥×*}ÐËMe~¬‚5 7*}vÐw†û@/S¬y}gЇ}IЕާõ¥/ z{ÂÇ©Ÿágcc,pœ±ÜAk:pôãàÿŸ¦z‚ endstream endobj startxref 418730 %%EOF ipe-7.1.4/build/doc/sync_off.png0000644000175000017500000000152512120621776016341 0ustar otfriedotfried‰PNG  IHDRàw=øIDATxíÝKhTWÀñÿä1I&3™8M¦Iš™†I3Ú©b$cÌ I1V1±-(Tö±±Ð.* t!‚K[¥Ä¥ˆ„¨´f£`l(øl©"Y”¤6ÆgÌTú}·sgîܹ ±d{8?æÌ¹÷;çÜuíÚ`:!±F¬¢BäŠ?ŰÄm'yÊÅ>ÑlU¯½üý‰è_‹?€Œê ]€Y(ŠNñ±8fý1°Öqún-eâ¨øtºmâÈ Ó0}b›ù%·©µ×Œ®=Ÿ0´³?Š1sŸ‹0€¯8À‘;_ ‹W|%\ Zð— >舽ln¨p©.aÇ{ )t;Ú b nŸš¯›65°¢¡2çÅÔ?Žž>Oдàuönm¤¢Ì`×­Z¬WjC~>‘Ö¾0+á {{©fÝ×Mæ·æÅ•ìÙ¼˜` Ý›%uA6´½ÅÆö¨Á,]k¢ÄW¼™u±›]‹ˆ7§¯iòh€ ¶¶¬ÏÖu1 ló —Ҷ̺–:ÞÍ\ÄcãÏxøhR²Êè‡Qt$¿ß§¨ ª fdºü<4BÿÙ[•f¸d7=.Mé9/—éªÃëù/ÿO Üaàò}€,‘j?Ÿõ.5Úšm?œÿŸ®ŽXÿ2¬#¸d píæ(£?cÛú¼!½›a1¥Þ—ŽòØ©ܾ7dÔK:‚ùÒ‰ì)Ê3‚Ü™àÌà]€,±H€µ+køöäu<|`·LhC7¹ÔeÍ Ÿ×Ÿ˜tÜ‹ óH$^2%l.êaeÐäýE”ÌÉ|ÅÜìî‰Ýsä }¸ýDû^hzé~ðR›¦Ã¡¿]|#ü¯@×—Ö‡[k¹–<|š(Ç*€Ý¹dÇtMé:Ýñø«Ø,êÅû¢]”' øXÓ_nò¡Æ|Øý /c§fžâOIEND®B`‚ipe-7.1.4/build/doc/classipe_1_1_snap.html0000644000175000017500000005066212120621776020205 0ustar otfriedotfried Ipelib: ipe::Snap Class Reference

#include <ipesnap.h>

Public Types

enum  TSnapModes {
  ESnapNone = 0, ESnapVtx = 1, ESnapBd = 2, ESnapInt = 4,
  ESnapGrid = 8, ESnapAngle = 0x10, ESnapAuto = 0x20
}

Public Member Functions

bool intersectionSnap (Vector &pos, const Page *page, double snapDist) const
bool snapAngularIntersection (Vector &pos, const Line &l, const Page *page, double snapDist) const
bool simpleSnap (Vector &pos, const Page *page, double snapDist) const
bool snap (Vector &pos, const Page *page, double snapDist, Vector *autoOrg=0) const
Line getLine (const Vector &mouse, const Vector &base) const
bool setEdge (const Vector &pos, const Page *page)

Public Attributes

int iSnap
bool iGridVisible
int iGridSize
double iAngleSize
int iSnapDistance
bool iWithAxes
Vector iOrigin
Angle iDir

Detailed Description

Performs snapping operations, and stores snapping state.

Member Enumeration Documentation

The different snap modes as bitmasks.

Enumerator:
ESnapNone 
ESnapVtx 
ESnapBd 
ESnapInt 
ESnapGrid 
ESnapAngle 
ESnapAuto 

Member Function Documentation

bool Snap::intersectionSnap ( Vector pos,
const Page page,
double  snapDist 
) const

Perform intersection snapping.

bool Snap::snapAngularIntersection ( Vector pos,
const Line l,
const Page page,
double  snapDist 
) const

Perform snapping to intersection of angular line and pos.

bool Snap::simpleSnap ( Vector pos,
const Page page,
double  snapDist 
) const

Tries vertex, intersection, boundary, and grid snapping.

If snapping occurred, pos is set to the new user space position.

bool Snap::snap ( Vector pos,
const Page page,
double  snapDist,
Vector autoOrg = 0 
) const

Performs snapping of position pos.

Returns true if snapping occurred. In that case pos is set to the new user space position.

Automatic angular snapping occurs if autoOrg is not null — the value is then used as the origin for automatic angular snapping.

Line Snap::getLine ( const Vector mouse,
const Vector base 
) const

Find line through base with slope determined by angular snap size and direction.

bool Snap::setEdge ( const Vector pos,
const Page page 
)

Set axis origin and direction from edge near mouse.

Returns true if successful.

Member Data Documentation

int ipe::Snap::iSnap

Activated snapping modes (TSnapModes)

bool ipe::Snap::iGridVisible

Is the grid visible?

int ipe::Snap::iGridSize

Snap grid spacing.

double ipe::Snap::iAngleSize

Angle for angular snapping.

int ipe::Snap::iSnapDistance

Snap distance (in pixels).

bool ipe::Snap::iWithAxes

Show coordinate system?

Vector ipe::Snap::iOrigin

Origin of coordinate system.

Angle ipe::Snap::iDir

Direction of x-axis.


The documentation for this class was generated from the following files:
  • ipesnap.h
  • ipesnap.cpp

ipe-7.1.4/build/doc/classipe_1_1_cairo_painter.html0000644000175000017500000012571312120621776022063 0ustar otfriedotfried Ipelib: ipe::CairoPainter Class Reference

#include <ipecairopainter.h>

Inherits ipe::Painter.

Public Member Functions

 CairoPainter (const Cascade *sheet, Fonts *fonts, cairo_t *cc, double zoom, bool pretty)
virtual ~CairoPainter ()
void setDimmed (bool dim)
- Public Member Functions inherited from ipe::Painter
 Painter (const Cascade *style)
virtual ~Painter ()
void transform (const Matrix &m)
void untransform (TTransformations trans)
void translate (const Vector &v)
void push ()
void pop ()
void pushMatrix ()
void popMatrix ()
void newPath ()
void moveTo (const Vector &v)
void lineTo (const Vector &v)
void curveTo (const Vector &v1, const Vector &v2, const Vector &v3)
void curveTo (const Bezier &bezier)
void rect (const Rect &re)
void drawEllipse ()
void drawArc (const Arc &arc)
void closePath ()
void drawPath (TPathMode mode)
void drawBitmap (Bitmap bitmap)
void drawText (const Text *text)
void drawSymbol (Attribute symbol)
void addClipPath ()
void setStroke (Attribute color)
void setFill (Attribute color)
void setPen (Attribute pen)
void setDashStyle (Attribute dash)
void setLineCap (TLineCap cap)
void setLineJoin (TLineJoin join)
void setFillRule (TFillRule rule)
void setSymStroke (Attribute color)
void setSymFill (Attribute color)
void setSymPen (Attribute wid)
void setOpacity (Attribute opaq)
void setTiling (Attribute til)
void setGradient (Attribute grad)
const Cascadecascade () const
Color stroke () const
Color fill () const
const Matrixmatrix () const
Fixed pen () const
String dashStyle () const
void dashStyle (std::vector< double > &dashes, double &offset) const
TLineCap lineCap () const
TLineJoin lineJoin () const
TFillRule fillRule () const
Color symStroke () const
Color symFill () const
Fixed symPen () const
Fixed opacity () const
Attribute tiling () const
Attribute gradient () const

Protected Member Functions

virtual void doPush ()
virtual void doPop ()
virtual void doMoveTo (const Vector &v)
virtual void doLineTo (const Vector &v)
virtual void doCurveTo (const Vector &v1, const Vector &v2, const Vector &v3)
virtual void doClosePath ()
virtual void doDrawArc (const Arc &arc)
virtual void doAddClipPath ()
virtual void doDrawPath (TPathMode mode)
virtual void doDrawBitmap (Bitmap bitmap)
virtual void doDrawText (const Text *text)
- Protected Member Functions inherited from ipe::Painter
virtual void doNewPath ()
virtual void doDrawSymbol (Attribute symbol)
void drawArcAsBezier (double alpha)

Additional Inherited Members

- Protected Attributes inherited from ipe::Painter
std::list< StateiState
std::list< MatrixiMatrix
const CascadeiCascade
int iInPath

Detailed Description

Ipe Painter using Cairo and Freetype as a backend.

This painter draws to a Cairo surface.

Constructor & Destructor Documentation

CairoPainter::CairoPainter ( const Cascade sheet,
Fonts fonts,
cairo_t *  cc,
double  zoom,
bool  pretty 
)

Construct a painter.

zoom one means 72 pixels per inch. Set pretty to true to avoid drawing text without Latex.

virtual ipe::CairoPainter::~CairoPainter ( )
inlinevirtual

Member Function Documentation

void ipe::CairoPainter::setDimmed ( bool  dim)
inline
void CairoPainter::doPush ( )
protectedvirtual

Perform graphics state push on output medium.

Reimplemented from ipe::Painter.

void CairoPainter::doPop ( )
protectedvirtual

Perform graphics state pop on output medium.

Reimplemented from ipe::Painter.

void CairoPainter::doMoveTo ( const Vector v)
protectedvirtual

Perform moveto operator.

The transformation matrix has already been applied.

Reimplemented from ipe::Painter.

void CairoPainter::doLineTo ( const Vector v)
protectedvirtual

Perform lineto operator.

The transformation matrix has already been applied.

Reimplemented from ipe::Painter.

void CairoPainter::doCurveTo ( const Vector v1,
const Vector v2,
const Vector v3 
)
protectedvirtual

Perform curveto operator.

The transformation matrix has already been applied.

Reimplemented from ipe::Painter.

void CairoPainter::doClosePath ( )
protectedvirtual

Perform closepath operator.

Reimplemented from ipe::Painter.

void CairoPainter::doDrawArc ( const Arc arc)
protectedvirtual

Draw an elliptic arc.

The default implementations calls drawArcAsBezier(). The transformation matrix has not yet been applied to arc.

Reimplemented from ipe::Painter.

void CairoPainter::doAddClipPath ( )
protectedvirtual

Add a clip path.

Reimplemented from ipe::Painter.

void CairoPainter::doDrawPath ( TPathMode  mode)
protectedvirtual

Actually draw the path.

Reimplemented from ipe::Painter.

void CairoPainter::doDrawBitmap ( Bitmap  bitmap)
protectedvirtual

Draw a bitmap.

Reimplemented from ipe::Painter.

void CairoPainter::doDrawText ( const Text text)
protectedvirtual

Draw a text object.

Reimplemented from ipe::Painter.


The documentation for this class was generated from the following files:
  • ipecairopainter.h
  • ipecairopainter.cpp

ipe-7.1.4/build/doc/classipe_1_1_text.html0000644000175000017500000022600312120621776020222 0ustar otfriedotfried Ipelib: ipe::Text Class Reference

#include <ipetext.h>

Inherits ipe::Object.

Classes

struct  XForm

Public Types

enum  TextType { ELabel = 1, EMinipage }
- Public Types inherited from ipe::Object
enum  Type {
  EGroup, EPath, EText, EImage,
  EReference
}

Public Member Functions

 Text ()
 Text (const AllAttributes &attr, String data, const Vector &pos, TextType type, double width=10.0)
 Text (const Text &rhs)
 ~Text ()
 Text (const XmlAttributes &attr, String data)
virtual Objectclone () const
virtual TextasText ()
virtual Type type () const
virtual void saveAsXml (Stream &stream, String layer) const
virtual void draw (Painter &painter) const
virtual void drawSimple (Painter &painter) const
virtual void accept (Visitor &visitor) const
virtual void addToBBox (Rect &box, const Matrix &m, bool) const
virtual double distance (const Vector &v, const Matrix &m, double bound) const
virtual void snapVtx (const Vector &mouse, const Matrix &m, Vector &pos, double &bound) const
virtual void checkStyle (const Cascade *sheet, AttributeSeq &seq) const
virtual bool setAttribute (Property prop, Attribute value, Attribute stroke, Attribute fill)
virtual Attribute getAttribute (Property prop)
Vector align () const
TextType textType () const
Vector position () const
String text () const
void setStroke (Attribute stroke)
void setOpacity (Attribute opaq)
Attribute stroke () const
Attribute size () const
Attribute style () const
Attribute opacity () const
bool isMinipage () const
void setTextType (TextType type)
THorizontalAlignment horizontalAlignment () const
TVerticalAlignment verticalAlignment () const
void setHorizontalAlignment (THorizontalAlignment align)
void setVerticalAlignment (TVerticalAlignment align)
double width () const
double height () const
double depth () const
double totalHeight () const
void setSize (Attribute size)
void setStyle (Attribute style)
void setWidth (double width)
void setText (String text)
bool isInternal () const
void setXForm (XForm *xform) const
const XFormgetXForm () const
- Public Member Functions inherited from ipe::Object
virtual ~Object ()=0
virtual GroupasGroup ()
virtual PathasPath ()
virtual ImageasImage ()
virtual ReferenceasReference ()
virtual TPinned pinned () const
void setPinned (TPinned pin)
TTransformations transformations () const
void setTransformations (TTransformations trans)
void setMatrix (const Matrix &matrix)
const Matrixmatrix () const
virtual void snapBnd (const Vector &mouse, const Matrix &m, Vector &pos, double &bound) const

Static Public Member Functions

static TVerticalAlignment makeVAlign (String str, TVerticalAlignment def)
static THorizontalAlignment makeHAlign (String str, THorizontalAlignment def)
static void saveAlignment (Stream &stream, THorizontalAlignment h, TVerticalAlignment v)

Additional Inherited Members

- Protected Member Functions inherited from ipe::Object
 Object ()
 Object (const AllAttributes &attr)
 Object (const Object &rhs)
 Object (const XmlAttributes &attr)
void saveAttributesAsXml (Stream &stream, String layer) const
- Static Protected Member Functions inherited from ipe::Object
static void checkSymbol (Kind kind, Attribute attr, const Cascade *sheet, AttributeSeq &seq)
- Protected Attributes inherited from ipe::Object
Matrix iMatrix
TPinned iPinned: 8
TTransformations iTransformations: 8

Detailed Description

The text object.

The text object stores a Latex source representation, which needs to be translated into PDF by Pdflatex before it can be saved as PDF.

There are two types of text objects: labels and minipages. The textType() method tells you which, or use isMinipage().

The dimensions of a text object are given by width(), height(), and depth(). They are recomputed by Ipe when running LaTeX, with the exception of the width for minipage objects (whose width is fixed). Before Latex has been run, the dimensions are not reliable.

The position of the reference point relative to the text box is given by verticalAlignment() and horizontalAlignment().

The text() must be a legal LaTeX fragment that can be interpreted by LaTeX inside \hbox, possibly using the macros or packages defined in the preamble.

Member Enumeration Documentation

Enumerator:
ELabel 
EMinipage 

Constructor & Destructor Documentation

Text::Text ( )
explicit

Construct an empty internal text object.

Text::Text ( const AllAttributes attr,
String  data,
const Vector pos,
TextType  type,
double  width = 10.0 
)
explicit

Create text object.

Text::Text ( const Text rhs)

Copy constructor.

Text::~Text ( )

Destructor.

Text::Text ( const XmlAttributes attr,
String  data 
)
explicit

Create from XML stream.

Member Function Documentation

Object * Text::clone ( ) const
virtual

Clone object.

Implements ipe::Object.

Text * Text::asText ( )
virtual

Return pointer to this object.

Reimplemented from ipe::Object.

Object::Type Text::type ( ) const
virtual

Implements ipe::Object.

void Text::saveAsXml ( Stream stream,
String  layer 
) const
virtual

Save object to XML stream.

Implements ipe::Object.

void Text::draw ( Painter painter) const
virtual

Save text as PDF.

Implements ipe::Object.

void Text::drawSimple ( Painter painter) const
virtual

Draw simple version for selecting and transforming.

Implements ipe::Object.

void Text::accept ( Visitor visitor) const
virtual

Call visitText of visitor.

Implements ipe::Object.

void Text::addToBBox ( Rect box,
const Matrix m,
bool  cp 
) const
virtual

Extend box to include the object transformed by m.

For objects in a page, don't call this directly. The Page caches the bounding box of each object, so it is far more efficient to call Page::bbox.

Control points that lie outside the visual object are included if cp is true.

If called with an empty box and cp == false, the result of this function is a tight bounding box for the object, with a little leeway in case the boundary is determined by a spline (it has to be approximated to perform this operation).

Implements ipe::Object.

double Text::distance ( const Vector v,
const Matrix m,
double  bound 
) const
virtual

Return distance of transformed object to point v. If larger than bound, can just return bound.

Implements ipe::Object.

void Text::snapVtx ( const Vector mouse,
const Matrix m,
Vector pos,
double &  bound 
) const
virtual

Compute possible vertex snapping position for transformed object.

Looks only for positions closer than bound. If successful, modify pos and bound.

Implements ipe::Object.

void Text::checkStyle ( const Cascade sheet,
AttributeSeq seq 
) const
virtual

Check symbolic size attribute.

Reimplemented from ipe::Object.

bool Text::setAttribute ( Property  prop,
Attribute  value,
Attribute  stroke,
Attribute  fill 
)
virtual

Set an attribute on this object.

Returns true if an attribute was actually changed. The arguments stroke and fill are only used then prop is EPropPathMode, and stroking or filling is added to an object that didn't have it before.

Reimplemented from ipe::Object.

Attribute Text::getAttribute ( Property  prop)
virtual

Get setting of an attribute of this object.

If object does not have this attribute, returnes "undefined" attribute.

Reimplemented from ipe::Object.

Vector Text::align ( ) const

Return position of reference point in text box coordinate system.

Assume a coordinate system where the text box has corners (0,0) and (Width(), TotalHeight()). This function returns the coordinates of the reference point in this coordinate system.

Text::TextType Text::textType ( ) const

Return type of text object.

Vector ipe::Text::position ( ) const
inline

Return text position.

String ipe::Text::text ( ) const
inline

Return text source.

void Text::setStroke ( Attribute  stroke)

Set stroke color.

void Text::setOpacity ( Attribute  opaq)

Set opacity of the object.

Attribute ipe::Text::stroke ( ) const
inline

Return stroke color.

Attribute ipe::Text::size ( ) const
inline

Return font size.

Attribute ipe::Text::style ( ) const
inline

Return Latex style of text object.

Attribute ipe::Text::opacity ( ) const
inline

Return opacity of the opject.

bool ipe::Text::isMinipage ( ) const
inline

Return true if text object is formatted as a minipage.

Equivalent to type being EMinipage.

void Text::setTextType ( TextType  type)

Change type.

THorizontalAlignment ipe::Text::horizontalAlignment ( ) const
inline

Return horizontal alignment of text object.

TVerticalAlignment ipe::Text::verticalAlignment ( ) const
inline

Return vertical alignment of text object.

void Text::setHorizontalAlignment ( THorizontalAlignment  align)

Change horizontal alignment (text moves with respect to reference point).

void Text::setVerticalAlignment ( TVerticalAlignment  align)

Change vertical alignment (text moves with respect to reference point).

TVerticalAlignment Text::makeVAlign ( String  str,
TVerticalAlignment  def 
)
static

Return vertical alignment indicated by a name, or else default.

THorizontalAlignment Text::makeHAlign ( String  str,
THorizontalAlignment  def 
)
static

Return horizontal alignment indicated by a name, or else default.

void Text::saveAlignment ( Stream stream,
THorizontalAlignment  h,
TVerticalAlignment  v 
)
static
double ipe::Text::width ( ) const
inline

Return width of text object.

double ipe::Text::height ( ) const
inline

Return height of text object (from baseline to top).

double ipe::Text::depth ( ) const
inline

Return depth of text object.

double ipe::Text::totalHeight ( ) const
inline

Return height + depth of text object.

void Text::setSize ( Attribute  size)

Set font size of text.

This invalidates (and destroys) the XForm.

void Text::setStyle ( Attribute  style)

Set Latex style of text.

This invalidates (and destroys) the XForm.

void Text::setWidth ( double  width)

Set width of paragraph.

This invalidates (and destroys) the XForm. The function panics if object is not a (true) minipage.

void Text::setText ( String  text)

Sets the text of the text object.

This invalidates (and destroys) the XForm.

bool ipe::Text::isInternal ( ) const
inline
void Text::setXForm ( XForm xform) const

Update the PDF code for this object.

const Text::XForm * ipe::Text::getXForm ( ) const
inline

Return the PDF representation of this text object.

If Pdflatex has not been run yet, returns 0.


The documentation for this class was generated from the following files:
  • ipetext.h
  • ipetext.cpp

ipe-7.1.4/build/doc/structipe_1_1_ipelet_data.html0000644000175000017500000001555412120621776021737 0ustar otfriedotfried Ipelib: ipe::IpeletData Struct Reference
ipe::IpeletData Struct Reference

#include <ipelet.h>

Public Attributes

PageiPage
const DocumentiDoc
int iPageNo
int iView
int iLayer
AllAttributes iAttributes
Snap iSnap

Detailed Description

Information provided to an ipelet when it is run.

Member Data Documentation

Page* ipe::IpeletData::iPage
const Document* ipe::IpeletData::iDoc
int ipe::IpeletData::iPageNo
int ipe::IpeletData::iView
int ipe::IpeletData::iLayer
AllAttributes ipe::IpeletData::iAttributes
Snap ipe::IpeletData::iSnap

The documentation for this struct was generated from the following file:
  • ipelet.h

ipe-7.1.4/build/doc/functions_0x78.html0000644000175000017500000001132212120621776017505 0ustar otfriedotfried Ipelib: Class Members
Here is a list of all class members with links to the classes they belong to:

- x -


ipe-7.1.4/build/doc/classes.html0000644000175000017500000005531212120621776016353 0ustar otfriedotfried Ipelib: Class Index
Class Index
A | B | C | D | E | F | G | I | L | M | O | P | R | S | T | V | X
  A  
CurveSegment (ipe)   Ipelet (ipe)   PdfDict (ipe)   Painter::State (ipe)   
  D  
IpeletData (ipe)   PdfFile (ipe)   Gradient::Stop (ipe)   
A85Source (ipe)   IpeletHelper (ipe)   PdfName (ipe)   Stream (ipe)   
A85Stream (ipe)   DataSource (ipe)   
  L  
PdfNull (ipe)   String (ipe)   
AllAttributes (ipe)   DeflateStream (ipe)   PdfNumber (ipe)   StringStream (ipe)   
Angle (ipe)   Document (ipe)   Latex (ipe)   PdfObj (ipe)   CanvasBase::Style (ipe)   
Arc (ipe)   
  E  
Layout (ipe)   PdfPainter (ipe)   StyleSheet (ipe)   
Attribute (ipe)   Lex (ipe)   PdfParser (ipe)   SubPath (ipe)   
  B  
Effect (ipe)   Line (ipe)   PdfRef (ipe)   Symbol (ipe)   
Ellipse (ipe)   Linear (ipe)   PdfString (ipe)   
  T  
Base64Source (ipe)   
  F  
  M  
PdfToken (ipe)   
Base64Stream (ipe)   PdfWriter (ipe)   TellStream (ipe)   
BBoxPainter (ipe)   Face (ipe)   Matrix (ipe)   Platform (ipe)   Text (ipe)   
Bezier (ipe)   FileSource (ipe)   Bitmap::MRenderData (ipe)   PsPainter (ipe)   TextPadding (ipe)   
Bitmap (ipe)   FileStream (ipe)   
  O  
PsWriter (ipe)   Thumbnail (ipe)   
BitmapFinder (ipe)   Fixed (ipe)   
  R  
Tiling (ipe)   
Buffer (ipe)   Font (ipe)   Object (ipe)   StyleSheet::TitleStyle (ipe)   
BufferSource (ipe)   Fonts (ipe)   ObjectFactory (ipe)   Rect (ipe)   Tool (ipe)   
  C  
  G  
  P  
Reference (ipe)   TransformTool (ipe)   
Repository (ipe)   
  V  
CairoPainter (ipe)   Gradient (ipe)   Page (ipe)   
  S  
Canvas (ipe)   Group (ipe)   StyleSheet::PageNumberStyle (ipe)   Vector (ipe)   
CanvasBase (ipe)   
  I  
PageSelector (ipe)   Segment (ipe)   Visitor (ipe)   
CanvasObserver (ipe)   Painter (ipe)   SelectTool (ipe)   
  X  
Cascade (ipe)   Image (ipe)   PanTool (ipe)   Shape (ipe)   
ClosedSpline (ipe)   ImlParser (ipe)   Path (ipe)   Snap (ipe)   Text::XForm (ipe)   
Color (ipe)   InflateSource (ipe)   PdfArray (ipe)   SelectTool::SObj (ipe)   XmlAttributes (ipe)   
Curve (ipe)   IpeAutoPtr   PdfBool (ipe)   Document::SProperties (ipe)   XmlParser (ipe)   
A | B | C | D | E | F | G | I | L | M | O | P | R | S | T | V | X

ipe-7.1.4/build/doc/namespacemembers.html0000644000175000017500000003760112120621776020226 0ustar otfriedotfried Ipelib: Namespace Members
Here is a list of all namespace members with links to the namespace documentation for each member:

- a -

  • abs() : ipe
  • AttributeSeq : ipe

- e -

  • EAlignBaseline : ipe
  • EAlignBottom : ipe
  • EAlignHCenter : ipe
  • EAlignLeft : ipe
  • EAlignRight : ipe
  • EAlignTop : ipe
  • EAlignVCenter : ipe
  • EAngleSize : ipe
  • EArrowSize : ipe
  • EBevelJoin : ipe
  • EButtCap : ipe
  • EColor : ipe
  • EDashStyle : ipe
  • EDefaultCap : ipe
  • EDefaultJoin : ipe
  • EDefaultRule : ipe
  • EEffect : ipe
  • EEvenOddRule : ipe
  • EFilledOnly : ipe
  • EFixedPin : ipe
  • EGradient : ipe
  • EGridSize : ipe
  • EHorizontalPin : ipe
  • EMiterJoin : ipe
  • ENoPin : ipe
  • ENotSelected : ipe
  • EOpacity : ipe
  • EPen : ipe
  • EPrimarySelected : ipe
  • EPropDashStyle : ipe
  • EPropFArrow : ipe
  • EPropFArrowShape : ipe
  • EPropFArrowSize : ipe
  • EPropFillColor : ipe
  • EPropFillRule : ipe
  • EPropGradient : ipe
  • EPropHorizontalAlignment : ipe
  • EPropLineCap : ipe
  • EPropLineJoin : ipe
  • EPropMarkShape : ipe
  • EPropMinipage : ipe
  • EPropOpacity : ipe
  • EPropPathMode : ipe
  • EPropPen : ipe
  • EPropPinned : ipe
  • EPropRArrow : ipe
  • EPropRArrowShape : ipe
  • EPropRArrowSize : ipe
  • EPropStrokeColor : ipe
  • EPropSymbolSize : ipe
  • EPropTextSize : ipe
  • EPropTextStyle : ipe
  • EPropTiling : ipe
  • EPropTransformableText : ipe
  • EPropTransformations : ipe
  • EPropVerticalAlignment : ipe
  • EPropWidth : ipe
  • ERoundCap : ipe
  • ERoundJoin : ipe
  • ESecondarySelected : ipe
  • ESquareCap : ipe
  • EStrokedAndFilled : ipe
  • EStrokedOnly : ipe
  • ESymbol : ipe
  • ESymbolSize : ipe
  • ETextSize : ipe
  • ETextStretch : ipe
  • ETextStyle : ipe
  • ETiling : ipe
  • ETransformationsAffine : ipe
  • ETransformationsRigidMotions : ipe
  • ETransformationsTranslations : ipe
  • EVerticalPin : ipe
  • EWindRule : ipe

- f -

  • FILE_FORMAT : ipe

- i -

  • IPELIB_VERSION : ipe
  • IpeQ() : ipe

- k -

- m -

- o -

  • OLDEST_FILE_FORMAT : ipe

- p -

  • Property : ipe
  • property_names : ipe

- q -

- t -

  • TFillRule : ipe
  • THorizontalAlignment : ipe
  • TLineCap : ipe
  • TLineJoin : ipe
  • TPathMode : ipe
  • TPinned : ipe
  • TSelect : ipe
  • TTransformations : ipe
  • TVerticalAlignment : ipe

ipe-7.1.4/build/doc/structipe_1_1_document_1_1_s_properties.html0000644000175000017500000002452712120621776024540 0ustar otfriedotfried Ipelib: ipe::Document::SProperties Struct Reference
ipe::Document::SProperties Struct Reference

#include <ipedoc.h>

Public Member Functions

 SProperties ()

Public Attributes

String iTitle
String iAuthor
String iSubject
String iKeywords
String iPreamble
bool iFullScreen
bool iNumberPages
String iCreated
String iModified
String iCreator

Detailed Description

Properties of a document.

Constructor & Destructor Documentation

Document::SProperties::SProperties ( )

Constructor clears the boolean flags.

Member Data Documentation

String ipe::Document::SProperties::iTitle
String ipe::Document::SProperties::iAuthor
String ipe::Document::SProperties::iSubject
String ipe::Document::SProperties::iKeywords
String ipe::Document::SProperties::iPreamble
bool ipe::Document::SProperties::iFullScreen
bool ipe::Document::SProperties::iNumberPages
String ipe::Document::SProperties::iCreated

Date/time in PDF style "D:20010428191400" format.

String ipe::Document::SProperties::iModified
String ipe::Document::SProperties::iCreator

Program that created this document (e.g. "Ipe 7.5").


The documentation for this struct was generated from the following files:
  • ipedoc.h
  • ipedoc.cpp

ipe-7.1.4/build/doc/classipe_1_1_pdf_array.html0000644000175000017500000003254712120621776021215 0ustar otfriedotfried Ipelib: ipe::PdfArray Class Reference
ipe::PdfArray Class Reference

#include <ipepdfparser.h>

Inherits ipe::PdfObj.

Public Member Functions

 PdfArray ()
 ~PdfArray ()
virtual const PdfArrayarray () const
virtual void write (Stream &stream) const
void append (const PdfObj *)
int count () const
const PdfObjobj (int index, const PdfFile *file) const
- Public Member Functions inherited from ipe::PdfObj
virtual ~PdfObj ()=0
virtual const PdfNullnull () const
virtual const PdfBoolboolean () const
virtual const PdfNumbernumber () const
virtual const PdfStringstring () const
virtual const PdfNamename () const
virtual const PdfRefref () const
virtual const PdfDictdict () const
String repr () const

Detailed Description

The PDF array object.

Constructor & Destructor Documentation

ipe::PdfArray::PdfArray ( )
inlineexplicit
PdfArray::~PdfArray ( )

Member Function Documentation

const PdfArray * PdfArray::array ( ) const
virtual

Return this object as PDF array object.

Reimplemented from ipe::PdfObj.

void PdfArray::write ( Stream stream) const
virtual

Implements ipe::PdfObj.

void PdfArray::append ( const PdfObj obj)

Append an object to array.

Array takes ownership of the object.

int ipe::PdfArray::count ( ) const
inline
const PdfObj * PdfArray::obj ( int  index,
const PdfFile file 
) const

Return object with index in array.

Indirect objects (references) are looked up if file is not zero, and the object referred to is returned (0 if it does not exist). Object remains owned by array.


The documentation for this class was generated from the following files:
  • ipepdfparser.h
  • ipepdfparser.cpp

ipe-7.1.4/build/doc/manual_22.html0000644000175000017500000000543612120621776016500 0ustar otfriedotfried Ipe Manual -- 5.1 Grid snapping
5.2 Context snapping5 Snapping5.1 Grid snapping

5.1 Grid snapping

Grid snapping is easy to explain. It simply means that the mouse position is rounded to the nearest grid point. Grid points are points whose coordinates are integer multiples of the grid size, which can be set in the box in the Snap field. You have a choice from a set of possible grid sizes. The units are Postscript points (in LaTeX called bp), which are equal to 1/72 of an inch.

You can ask Ipe to show the grid points by selecting the function Grid visible from the View menu. The same function turns it off again.

ipe-7.1.4/build/doc/classipe_1_1_select_tool.html0000644000175000017500000003112012120621776021544 0ustar otfriedotfried Ipelib: ipe::SelectTool Class Reference
ipe::SelectTool Class Reference

#include <ipetool.h>

Inherits ipe::Tool.

Classes

struct  SObj

Public Member Functions

 SelectTool (CanvasBase *canvas, Page *page, int view, double selectDistance, bool nonDestructive)
virtual void draw (Painter &painter) const
virtual void mouseButton (int button, bool press)
virtual void mouseMove ()
virtual bool key (int code, int modifiers, String text)
- Public Member Functions inherited from ipe::Tool
virtual ~Tool ()

Additional Inherited Members

- Protected Member Functions inherited from ipe::Tool
 Tool (CanvasBase *canvas)
- Protected Attributes inherited from ipe::Tool
CanvasBaseiCanvas

Detailed Description

A tool for selecting objects.

Constructor & Destructor Documentation

SelectTool::SelectTool ( CanvasBase canvas,
Page page,
int  view,
double  selectDistance,
bool  nonDestructive 
)

Constructor starts selection.

Member Function Documentation

void SelectTool::draw ( Painter painter) const
virtual

Implements ipe::Tool.

void SelectTool::mouseButton ( int  button,
bool  press 
)
virtual

Called when a mouse button is pressed or released on the canvas.

button is 1, 2, or 3, with Shift/Ctrl/Alt/Meta modifiers added in (as defined in CanvasBase::TModifiers. press is true for button-down, and false for button-up.

Reimplemented from ipe::Tool.

void SelectTool::mouseMove ( )
virtual

Called when the mouse is moved on the canvas.

Reimplemented from ipe::Tool.

bool SelectTool::key ( int  code,
int  modifiers,
String  text 
)
virtual

Called when a key is pressed.

modifiers are as defined in CanvasBase::TModifiers.

Reimplemented from ipe::Tool.


The documentation for this class was generated from the following files:
  • ipetool.h
  • ipetool.cpp

ipe-7.1.4/build/doc/classipe_1_1_fixed.html0000644000175000017500000004144512120621776020342 0ustar otfriedotfried Ipelib: ipe::Fixed Class Reference

#include <ipebase.h>

Public Member Functions

 Fixed (int val)
 Fixed ()
int toInt () const
double toDouble () const
int internal () const
Fixed mult (int a, int b) const
bool operator== (const Fixed &rhs) const
bool operator!= (const Fixed &rhs) const
bool operator< (const Fixed &rhs) const

Static Public Member Functions

static Fixed fromInternal (int val)
static Fixed fromDouble (double val)

Friends

Streamoperator<< (Stream &stream, const Fixed &f)

Related Functions

(Note that these are not member functions.)

Streamoperator<< (Stream &stream, const Fixed &f)

Detailed Description

Fixed point number with three (decimal) fractional digits.

Constructor & Destructor Documentation

ipe::Fixed::Fixed ( int  val)
inlineexplicit
ipe::Fixed::Fixed ( )
inlineexplicit

Member Function Documentation

Fixed ipe::Fixed::fromInternal ( int  val)
inlinestatic
Fixed Fixed::fromDouble ( double  val)
static
int ipe::Fixed::toInt ( ) const
inline
double ipe::Fixed::toDouble ( ) const
inline
int ipe::Fixed::internal ( ) const
inline
Fixed Fixed::mult ( int  a,
int  b 
) const

Return value times (a/b)

bool ipe::Fixed::operator== ( const Fixed rhs) const
inline
bool ipe::Fixed::operator!= ( const Fixed rhs) const
inline
bool ipe::Fixed::operator< ( const Fixed rhs) const
inline

Friends And Related Function Documentation

Stream& operator<< ( Stream stream,
const Fixed f 
)
friend
Stream & operator<< ( Stream stream,
const Fixed f 
)
related

The documentation for this class was generated from the following files:
  • ipebase.h
  • ipebase.cpp

ipe-7.1.4/build/doc/classipe_1_1_canvas_observer-members.html0000644000175000017500000000746112120621776024055 0ustar otfriedotfried Ipelib: Member List
ipe::CanvasObserver Member List

ipe-7.1.4/build/doc/classipe_1_1_canvas_base.html0000644000175000017500000021670312120621776021511 0ustar otfriedotfried Ipelib: ipe::CanvasBase Class Reference

#include <ipecanvas.h>

Inherited by ipe::Canvas, ipe::Canvas, and ipe::Canvas.

Classes

struct  Style

Public Types

enum  TModifiers { EShift = 0x100, EControl = 0x200, EAlt = 0x400, EMeta = 0x800 }
enum  TCursor { EStandardCursor, EHandCursor, ECrossCursor, EDotCursor }

Public Member Functions

virtual ~CanvasBase ()
void setPage (const Page *page, int pno, int view, const Cascade *sheet)
void setFontPool (const FontPool *fontPool)
Vector pan () const
double zoom () const
const Cascadecascade () const
Vector center () const
Vector pos () const
Vector unsnappedPos () const
Vector globalPos () const
Vector simpleSnapPos () const
const Snapsnap () const
int additionalModifiers () const
void setAdditionalModifiers (int mod)
Vector devToUser (const Vector &arg) const
Vector userToDev (const Vector &arg) const
void setCanvasStyle (const Style &style)
Style canvasStyle () const
void setPan (const Vector &v)
void setZoom (double zoom)
void setSnap (const Snap &s)
void setDimmed (bool dimmed)
void setAutoOrigin (const Vector &v)
Matrix canvasTfm () const
void setObserver (CanvasObserver *observer)
void setFifiVisible (bool visible)
void setSelectionVisible (bool visible)
void setTool (Tool *tool)
void finishTool ()
void update ()
void updateTool ()
int canvasWidth () const
int canvasHeight () const
virtual void setCursor (TCursor cursor, double w=1.0, Color *color=0)=0

Protected Member Functions

 CanvasBase ()
void drawPaper (cairo_t *cc)
void drawFrame (cairo_t *cc)
void drawAxes (cairo_t *cc)
void drawGrid (cairo_t *cc)
void drawObjects (cairo_t *cc)
void drawTool (Painter &painter)
bool snapToPaperAndFrame ()
void refreshSurface ()
void computeFifi (double x, double y)
virtual void invalidate ()=0
virtual void invalidate (int x, int y, int w, int h)=0

Protected Attributes

CanvasObserveriObserver
TooliTool
const PageiPage
int iPageNumber
int iView
const CascadeiCascade
Style iStyle
Vector iPan
double iZoom
Snap iSnap
bool iDimmed
bool iAutoSnap
Vector iAutoOrigin
int iAdditionalModifiers
bool iRepaintObjects
int iWidth
int iHeight
cairo_surface_t * iSurface
Vector iUnsnappedMousePos
Vector iMousePos
Vector iGlobalPos
Vector iOldFifi
bool iFifiVisible
bool iSelectionVisible
FontsiFonts

Member Enumeration Documentation

Keyboard modifiers.

Enumerator:
EShift 
EControl 
EAlt 
EMeta 
Enumerator:
EStandardCursor 
EHandCursor 
ECrossCursor 
EDotCursor 

Constructor & Destructor Documentation

CanvasBase::~CanvasBase ( )
virtual

destructor.

CanvasBase::CanvasBase ( )
protected

Construct a new canvas.

Member Function Documentation

void CanvasBase::setPage ( const Page page,
int  pno,
int  view,
const Cascade sheet 
)

Set the page to be displayed.

Doesn't take ownership of any argument. The page number pno is only needed if page numbering is turned on.

void CanvasBase::setFontPool ( const FontPool *  fontPool)

set information about Latex fonts (from ipe::Document)

Vector ipe::CanvasBase::pan ( ) const
inline

Return current pan.

double ipe::CanvasBase::zoom ( ) const
inline

Return current zoom.

const Cascade* ipe::CanvasBase::cascade ( ) const
inline

Return current style sheet cascade.

Vector ipe::CanvasBase::center ( ) const
inline

Return center of canvas.

Vector ipe::CanvasBase::pos ( ) const
inline

Return last mouse position (snapped!) in user coordinates.

Vector ipe::CanvasBase::unsnappedPos ( ) const
inline

Return last unsnapped mouse position in user coordinates.

Vector ipe::CanvasBase::globalPos ( ) const
inline

Return global mouse position of last mouse press/release.

Vector CanvasBase::simpleSnapPos ( ) const

Return snapped mouse position without angular snapping.

const Snap& ipe::CanvasBase::snap ( ) const
inline

Return current snapping information.

int ipe::CanvasBase::additionalModifiers ( ) const
inline

Return current additional modifiers.

void CanvasBase::setAdditionalModifiers ( int  mod)

Set additional modifiers.

These modifier bits are passed to the Tool when a key is pressed or a drawing action is performed in addition to the actual keyboard modifiers.

Vector CanvasBase::devToUser ( const Vector arg) const

Convert canvas (device) coordinates to user coordinates.

Vector CanvasBase::userToDev ( const Vector arg) const

Convert user coordinates to canvas (device) coordinates.

void CanvasBase::setCanvasStyle ( const Style style)

Set style of canvas drawing.

Includes paper color, pretty text, and grid.

Style ipe::CanvasBase::canvasStyle ( ) const
inline

Return canvas style.

void CanvasBase::setPan ( const Vector v)

Set current pan position.

The pan position is the user coordinate that is displayed at the very center of the canvas.

void CanvasBase::setZoom ( double  zoom)

Set current zoom factor.

The zoom factor maps user coordinates to screen pixel coordinates.

void CanvasBase::setSnap ( const Snap s)

Set the snapping information.

void CanvasBase::setDimmed ( bool  dimmed)

Dim whole canvas, except for the Tool.

This mode will be reset when the Tool finishes.

void CanvasBase::setAutoOrigin ( const Vector v)

Enable automatic angular snapping with this origin.

Matrix CanvasBase::canvasTfm ( ) const

Matrix mapping user coordinates to canvas coordinates.

void CanvasBase::setObserver ( CanvasObserver observer)

Set an observer.

Use 0 to delete current observer.

void CanvasBase::setFifiVisible ( bool  visible)

Set whether Fifi should be shown.

Fifi will only be shown if a snapping mode is active.

void CanvasBase::setSelectionVisible ( bool  visible)

Set whether selection should be shown when there is no tool.

void CanvasBase::setTool ( Tool tool)

Set a new tool.

Calls canvasObserverToolChanged().

void CanvasBase::finishTool ( )
void CanvasBase::update ( )

Mark for update with redrawing of objects.

void CanvasBase::updateTool ( )

Mark for update with redrawing of tool only.

int ipe::CanvasBase::canvasWidth ( ) const
inline
int ipe::CanvasBase::canvasHeight ( ) const
inline
virtual void ipe::CanvasBase::setCursor ( TCursor  cursor,
double  w = 1.0,
Color color = 0 
)
pure virtual

Implemented in ipe::Canvas.

void CanvasBase::drawPaper ( cairo_t *  cc)
protected
void CanvasBase::drawFrame ( cairo_t *  cc)
protected
void CanvasBase::drawAxes ( cairo_t *  cc)
protected
void CanvasBase::drawGrid ( cairo_t *  cc)
protected
void CanvasBase::drawObjects ( cairo_t *  cc)
protected
void CanvasBase::drawTool ( Painter painter)
protected

Draw the current canvas tool.

If no tool is set, it draws the selected objects.

bool CanvasBase::snapToPaperAndFrame ( )
protected
void CanvasBase::refreshSurface ( )
protected
void CanvasBase::computeFifi ( double  x,
double  y 
)
protected

Stores the mouse position in iUnsnappedMousePos, computes Fifi if snapping is enabled, and stores snapped position in iMousePos.

virtual void ipe::CanvasBase::invalidate ( )
protectedpure virtual

Implemented in ipe::Canvas.

virtual void ipe::CanvasBase::invalidate ( int  x,
int  y,
int  w,
int  h 
)
protectedpure virtual

Implemented in ipe::Canvas.

Member Data Documentation

CanvasObserver* ipe::CanvasBase::iObserver
protected
Tool* ipe::CanvasBase::iTool
protected
const Page* ipe::CanvasBase::iPage
protected
int ipe::CanvasBase::iPageNumber
protected
int ipe::CanvasBase::iView
protected
const Cascade* ipe::CanvasBase::iCascade
protected
Style ipe::CanvasBase::iStyle
protected
Vector ipe::CanvasBase::iPan
protected
double ipe::CanvasBase::iZoom
protected
Snap ipe::CanvasBase::iSnap
protected
bool ipe::CanvasBase::iDimmed
protected
bool ipe::CanvasBase::iAutoSnap
protected
Vector ipe::CanvasBase::iAutoOrigin
protected
int ipe::CanvasBase::iAdditionalModifiers
protected
bool ipe::CanvasBase::iRepaintObjects
protected
int ipe::CanvasBase::iWidth
protected
int ipe::CanvasBase::iHeight
protected
cairo_surface_t* ipe::CanvasBase::iSurface
protected
Vector ipe::CanvasBase::iUnsnappedMousePos
protected
Vector ipe::CanvasBase::iMousePos
protected
Vector ipe::CanvasBase::iGlobalPos
protected
Vector ipe::CanvasBase::iOldFifi
protected
bool ipe::CanvasBase::iFifiVisible
protected
bool ipe::CanvasBase::iSelectionVisible
protected
Fonts* ipe::CanvasBase::iFonts
protected

The documentation for this class was generated from the following files:
  • ipecanvas.h
  • ipecanvas.cpp

ipe-7.1.4/build/doc/structipe_1_1_style_sheet_1_1_page_number_style-members.html0000644000175000017500000000712012120621776027656 0ustar otfriedotfried Ipelib: Member List
ipe::StyleSheet::PageNumberStyle Member List

ipe-7.1.4/build/doc/classipe_1_1_page-members.html0000644000175000017500000004721412120621776021607 0ustar otfriedotfried Ipelib: Member List
ipe::Page Member List

This is the complete list of members for ipe::Page, including all inherited members.

active(int index) const ipe::Pageinline
addLayer(String name)ipe::Page
addLayer()ipe::Page
append(TSelect sel, int layer, Object *obj)ipe::Page
applyTitleStyle(const Cascade *sheet)ipe::Page
basic()ipe::Pagestatic
bbox(int i) const ipe::Page
clearViews()ipe::Page
count() const ipe::Pageinline
countLayers() const ipe::Pageinline
countMarkedViews() const ipe::Page
countViews() const ipe::Pageinline
deselectAll()ipe::Page
distance(int i, const Vector &v, double bound) const ipe::Page
effect(int index) const ipe::Pageinline
ensurePrimarySelection()ipe::Page
findLayer(String name) const ipe::Page
hasSelection() const ipe::Page
hasSnapping(int i) const ipe::Pageinline
insert(int i, TSelect sel, int layer, Object *obj)ipe::Page
insertView(int i, String active)ipe::Page
invalidateBBox(int i) const ipe::Page
isLocked(int i) const ipe::Pageinline
layer(int index) const ipe::Pageinline
layerOf(int i) const ipe::Pageinline
marked() const ipe::Pageinline
markedView(int index) const ipe::Pageinline
moveLayer(int index, int newIndex)ipe::Page
notes() const ipe::Pageinline
object(int i)ipe::Pageinline
object(int i) const ipe::Pageinline
objectVisible(int view, int objno) const ipe::Pageinline
Page()ipe::Pageexplicit
pageBBox(const Cascade *sheet) const ipe::Page
primarySelection() const ipe::Page
remove(int i)ipe::Page
removeLayer(String name)ipe::Page
removeView(int i)ipe::Page
renameLayer(String oldName, String newName)ipe::Page
replace(int i, Object *obj)ipe::Page
saveAsIpePage(Stream &stream) const ipe::Page
saveAsXml(Stream &stream) const ipe::Page
saveSelection(Stream &stream) const ipe::Page
section(int level) const ipe::Page
sectionUsesTitle(int level) const ipe::Pageinline
select(int i) const ipe::Pageinline
setActive(int index, String name)ipe::Page
setAttribute(int i, Property prop, Attribute value, Attribute stroke, Attribute fill)ipe::Page
setEffect(int index, Attribute sym)ipe::Page
setLayerOf(int i, int layer)ipe::Pageinline
setLocked(int i, bool flag)ipe::Page
setMarked(bool marked)ipe::Page
setMarkedView(int index, bool marked)ipe::Page
setNotes(String notes)ipe::Page
setSection(int level, bool useTitle, String name)ipe::Page
setSelect(int i, TSelect sel)ipe::Pageinline
setSnapping(int i, bool flag)ipe::Page
setTitle(String title)ipe::Page
setVisible(int view, String layer, bool vis)ipe::Page
snapBnd(int i, const Vector &mouse, Vector &pos, double &bound) const ipe::Page
snapVtx(int i, const Vector &mouse, Vector &pos, double &bound) const ipe::Page
textBox(const Cascade *sheet) const ipe::Page
title() const ipe::Page
titleText() const ipe::Page
transform(int i, const Matrix &m)ipe::Page
viewBBox(const Cascade *sheet, int view) const ipe::Page
visible(int view, int layer) const ipe::Pageinline

ipe-7.1.4/build/doc/structipe_1_1_select_tool_1_1_s_obj.html0000644000175000017500000000733512120621776023612 0ustar otfriedotfried Ipelib: ipe::SelectTool::SObj Struct Reference
ipe::SelectTool::SObj Struct Reference

#include <ipetool.h>

Public Attributes

int index
double distance

Member Data Documentation

int ipe::SelectTool::SObj::index
double ipe::SelectTool::SObj::distance

The documentation for this struct was generated from the following file:
  • ipetool.h

ipe-7.1.4/build/doc/classipe_1_1_inflate_source.html0000644000175000017500000001424712120621776022245 0ustar otfriedotfried Ipelib: ipe::InflateSource Class Reference
ipe::InflateSource Class Reference

#include <ipeutils.h>

Inherits ipe::DataSource.

Public Member Functions

 InflateSource (DataSource &source)
virtual ~InflateSource ()
virtual int getChar ()
- Public Member Functions inherited from ipe::DataSource
virtual ~DataSource ()=0

Detailed Description

Filter source adding flate decompression.

Constructor & Destructor Documentation

InflateSource::InflateSource ( DataSource source)
InflateSource::~InflateSource ( )
virtual

Member Function Documentation

int InflateSource::getChar ( )
virtual

Get one more character, or EOF.

Implements ipe::DataSource.


The documentation for this class was generated from the following files:
  • ipeutils.h
  • ipeutils.cpp

ipe-7.1.4/build/doc/manual_27.html0000644000175000017500000001743412120621776016506 0ustar otfriedotfried Ipe Manual -- 6 Stylesheets
7 PresentationsTop5 Snapping6 Stylesheets

6 Stylesheets

The symbolic attributes appearing in an Ipe document are translated to absolute values for rendering by a stylesheet that is attached to the document. Documents can have multiple "cascaded" stylesheets, the sheets form a stack, and symbols are looked up from top to bottom. At the bottom of any stylesheet cascade is always the minimal standard style sheet, which is built into Ipe.

When you create a new empty document, it automatically gets a copy of this standard style sheet (which does little more than define the "normal" attribute for each kind of attribute). In addition, Ipe inserts a predefined list of stylesheets. The list of these stylesheets can be customized using an ipelet, using Ipe's command line options, and an environment variable. By default, a new document gets the stylesheet basic that comes with Ipe.

The stylesheet dialog (in the Edit menu under Stylesheets) allows you to inspect the cascade of stylesheets associated with your document, to add and remove stylesheets, and to change their order. You can also save individual stylesheets.

The stylesheets of your document also determine the symbolic choices you have in the Ipe user interface. If you feel that Ipe does not offer you the right choice of colors, pen widths, etc., you are ready to make your own style sheet! Ipe's styles directory contains a few examples to look at. The colors.isy stylesheet defines all the colors of the X11 color database - you could make a selection of these for your own use.

When a stylesheet is "added" to an Ipe document, the contents of the stylesheet file is copied into the Ipe document. Subsequent modification of the stylesheet file has no effect on the Ipe document. The right way to modify your stylesheet is to either "add" it again, and then to delete the old copy from your stylesheet cascade (the one further down in the list), or to use the Update stylesheets function in the Edit menu. This function assumes that the stylesheet file is in the same directory as the document and that the filename coincides with the name of the stylesheet (plus the extension .isy).

Removing or replacing a stylesheet can cause some of the symbolic attributes in your document to become undefined. This is not a disaster—Ipe will simply use some default value for any undefined symbolic attribute. To allow you to diagnose the problem, Ipe will show a warning listing all undefined symbolic attributes.

The style sheet is also responsible for determining the paper and frame size. Ipe's default paper size is the ISO standard A4. If you wish to use letter size paper instead, include this style sheet:

   <ipestyle name="letterpaper">
     <layout paper="612 792" origin="0 0" frame="612 792"/>
   </ipestyle>

Symbols.

Style sheets can also contain symbols, such as marks and arrows, background patterns, or logos. These are named Ipe objects that can be referenced by the document. If your document's stylesheets define a symbol named Background, it will be displayed automatically on all pages. You can create and use symbols using the Symbols ipelet. Here is a (silly) example of a style sheet that defines such a background:

<ipestyle name="background">
<symbol name="Background" xform="yes">
<text pos="10 10" stroke="black" size="LARGE">
Background text
</text>
</symbol>
</ipestyle>

Note the use of the xform attribute—it ensures that the background is embedded only once into PDF document. This can make a huge difference if your background is a complicated object.

Symbols can be parameterized with a stroke color, fill color, pen size, and symbol size. This means that the actual value of these attributes is only set when the symbol is used in the document (not in the symbol definition). The name of a parameterized symbol must end with a pair of parentheses containing some of the letters "s" (stroke), "f" (fill), "p" (pen), "x" (symbol size), in this order. The symbol definition can then use the special attribute values sym-stroke, sym-fill, and sym-pen. A resizable symbol is automatically magnified by the symbol size set in the symbol reference.

You can also use a stylesheet to define additional mark shapes, arrow shapes, or tiling patterns.

Latex preamble.

Stylesheets can also define a piece of LaTeX-preamble for your document. When your text objects are processed by LaTeX, the preamble used consists of the pieces on the style sheet cascade, from bottom to top, followed by the preamble set for the document itself.

Transparency.

If you wish to use transparency in your document, you need to define opacity values in its stylesheet. The default stylesheet basic.isy does not define any opacity value, because documents using transparence cannot be saved in Postscript format. A minimal stylesheet defining an opacity value would be:

   <ipestyle name="transparency">
   <opacity name="50%" value="0.5"/>
   </ipestyle>

Other stylesheet definitions that are meant for PDF presentations are discussed in the next section.

ipe-7.1.4/build/doc/functions_0x76.html0000644000175000017500000001436012120621776017510 0ustar otfriedotfried Ipelib: Class Members
Here is a list of all class members with links to the classes they belong to:

- v -


ipe-7.1.4/build/doc/manual_4.html0000644000175000017500000000515212120621776016413 0ustar otfriedotfried Ipe Manual -- 3.1 Order of objects
3.2 The current selection3 General Concepts3.1 Order of objects

3.1 Order of objects

An Ipe drawing is a sequence of geometric objects. The order of the objects is important—wherever two objects overlap, the object which comes first in Ipe's sequence will hide the other ones. When new objects are created, they are added in front of all other objects. However, you can change the position of an object by putting it in front or in the back, using the "Front" and "Back" functions in the Edit menu.

ipe-7.1.4/build/doc/classipe_1_1_bitmap_finder.html0000644000175000017500000002142412120621776022041 0ustar otfriedotfried Ipelib: ipe::BitmapFinder Class Reference

#include <ipeutils.h>

Inherits ipe::Visitor.

Public Member Functions

void scanPage (const Page *page)
virtual void visitGroup (const Group *obj)
virtual void visitImage (const Image *obj)
- Public Member Functions inherited from ipe::Visitor
virtual ~Visitor ()
virtual void visitPath (const Path *obj)
virtual void visitText (const Text *obj)
virtual void visitReference (const Reference *obj)

Public Attributes

std::vector< BitmapiBitmaps

Detailed Description

A visitor that recursively scans objects and collects all bitmaps.

Member Function Documentation

void BitmapFinder::scanPage ( const Page page)
void BitmapFinder::visitGroup ( const Group obj)
virtual

Called on an Group object.

Reimplemented from ipe::Visitor.

void BitmapFinder::visitImage ( const Image obj)
virtual

Called on an Image object.

Reimplemented from ipe::Visitor.

Member Data Documentation

std::vector<Bitmap> ipe::BitmapFinder::iBitmaps

The documentation for this class was generated from the following files:
  • ipeutils.h
  • ipeutils.cpp

ipe-7.1.4/build/doc/nav_g.png0000644000175000017500000000013712120621776015623 0ustar otfriedotfried‰PNG  IHDRô1&IDATxíÝ1 ÁOHf„á_ ->~¸åM iËMèÀƒS½ü‚<IEND®B`‚ipe-7.1.4/build/doc/classipe_1_1_data_source.html0000644000175000017500000001276112120621776021533 0ustar otfriedotfried Ipelib: ipe::DataSource Class Reference
ipe::DataSource Class Reference

#include <ipebase.h>

Inherited by ipe::A85Source, ipe::Base64Source, ipe::BufferSource, ipe::FileSource, ipe::InflateSource, PsSource, and StandardStyleSource.

Public Member Functions

virtual ~DataSource ()=0
virtual int getChar ()=0

Detailed Description

Interface for getting data for parsing.

Constructor & Destructor Documentation

DataSource::~DataSource ( )
pure virtual

Pure virtual destructor.

Member Function Documentation

virtual int ipe::DataSource::getChar ( )
pure virtual

Get one more character, or EOF.

Implemented in ipe::BufferSource, ipe::FileSource, ipe::InflateSource, ipe::Base64Source, and ipe::A85Source.


The documentation for this class was generated from the following files:
  • ipebase.h
  • ipebase.cpp

ipe-7.1.4/build/doc/classipe_1_1_segment-members.html0000644000175000017500000001233712120621776022333 0ustar otfriedotfried Ipelib: Member List
ipe::Segment Member List

This is the complete list of members for ipe::Segment, including all inherited members.

distance(const Vector &v, double bound) const ipe::Segment
distance(const Vector &v) const ipe::Segment
intersects(const Segment &seg, Vector &pt) const ipe::Segment
intersects(const Line &l, Vector &pt) const ipe::Segment
iPipe::Segment
iQipe::Segment
line() const ipe::Segmentinline
project(const Vector &v, Vector &projection) const ipe::Segment
Segment()ipe::Segmentinline
Segment(const Vector &p, const Vector &q)ipe::Segmentinlineexplicit
snap(const Vector &mouse, Vector &pos, double &bound) const ipe::Segment

ipe-7.1.4/build/doc/classipe_1_1_deflate_stream-members.html0000644000175000017500000001534412120621776023651 0ustar otfriedotfried Ipelib: Member List
ipe::DeflateStream Member List

This is the complete list of members for ipe::DeflateStream, including all inherited members.

close()ipe::DeflateStreamvirtual
deflate(const char *data, int size, int &deflatedSize, int compressLevel)ipe::DeflateStreamstatic
DeflateStream(Stream &stream, int level)ipe::DeflateStream
operator<<(char ch)ipe::Streaminline
operator<<(const String &s)ipe::Streaminline
operator<<(const char *s)ipe::Streaminline
operator<<(int i)ipe::Stream
operator<<(double d)ipe::Stream
putChar(char ch)ipe::DeflateStreamvirtual
putCString(const char *s)ipe::Streamvirtual
putHexByte(char b)ipe::Stream
putRaw(const char *data, int size)ipe::Streamvirtual
putString(String s)ipe::Streamvirtual
putXmlString(String s)ipe::Stream
~DeflateStream()ipe::DeflateStreamvirtual
~Stream()ipe::Streamvirtual

ipe-7.1.4/build/doc/classipe_1_1_a85_source-members.html0000644000175000017500000000602312120621776022641 0ustar otfriedotfried Ipelib: Member List
ipe::A85Source Member List

This is the complete list of members for ipe::A85Source, including all inherited members.

A85Source(DataSource &source)ipe::A85Source
getChar()ipe::A85Sourcevirtual
~DataSource()=0ipe::DataSourcepure virtual

ipe-7.1.4/build/doc/functions_func_0x71.html0000644000175000017500000001066012120621776020515 0ustar otfriedotfried Ipelib: Class Members - Functions
 

- q -


ipe-7.1.4/build/doc/structipe_1_1_document_1_1_s_properties-members.html0000644000175000017500000001277712120621776026174 0ustar otfriedotfried Ipelib: Member List
ipe::Document::SProperties Member List

ipe-7.1.4/build/doc/functions_0x63.html0000644000175000017500000003633312120621776017510 0ustar otfriedotfried Ipelib: Class Members
Here is a list of all class members with links to the classes they belong to:

- c -


ipe-7.1.4/build/doc/manual_41.html0000644000175000017500000001024012120621776016466 0ustar otfriedotfried Ipe Manual -- 9 The Ipe file format
10 If you have used Ipe 6 beforeTop8 Advanced topics9 The Ipe file format

9 The Ipe file format

Ipe can store documents in several possible formats. Among them are standard PDF and Postscript, which can be read by any application capable of opening such files, such as Acrobat Reader, Xpdf, or Ghostview. (Ipe embeds its own information inside PDF and Postscript files. The way this is done is not documented here, and may change between releases of Ipe.)

There is one other Ipe file format, which is a pure XML implementation. Files stored in this format can be parsed with any XML-aware application, and you can create XML files for Ipe from your own applications.

A DTD for the Ipe format is available as ipe.dtd. For instance, you can use this to validate an Ipe document using

xmllint --valid --path <path-to-ipe.dtd> --noout <file.ipe>

The tags understood by Ipe are described informally in this section. Tags in the XML file can carry attributes other than the ones documented here. Ipe ignores all attributes it does't understand, and they will be lost if the document is saved again from Ipe. Ipe will complain about any XML elements not described here, with the exception that you can use elements whose name starts with "x-" freely to add your own information inside an Ipe file.

An Ipe XML file must contain exactly one <ipe> element, while an Ipe stylesheet file must contain exactly one <ipestyle> element (both types of files are allowed to start with an <?xml> tag, which is simply ignored by Ipe). An Ipe file may also contain a <!DOCTYPE> tag.

All elements are documented below.

ipe-7.1.4/build/doc/manual_43.html0000644000175000017500000001247212120621776016501 0ustar otfriedotfried Ipe Manual -- 9.2 The <page> element
9.3 Ipe object elements9 The Ipe file format9.1 The <ipe> element9.2 The <page> element

9.2 The <page> element

Attributes

title
(optional) title of this page (displayed at a fixed location in a format specified by the style sheet),
section
(optional) Title of document section starting with this page. If the attribute is not present, this page continues the section of the previous page. If the attribute is present, but its value is an empty string, then the contents of the title attribute is used instead.
subsection
(optional) Title of document subsection starting with this page. If the attribute is not present, this page continues the subsection of the previous page. If the attribute is present, but its value is an empty string, then the contents of the title attribute is used instead.
marked
(optional) The page is marked for printing unless the value of this attribute is no.

Contents

  1. An optional <notes> element,
  2. a possibly empty sequence of <layer> elements,
  3. a possibly empty sequence of <view> elements,
  4. a possibly empty sequence of Ipe object elements.

If a page contains no layer element, Ipe automatically adds a default layer named "alpha", visible and editable.

If a page contains no view element, a single view where all layers are visible is assumed.

9.2.1 The <notes> element

This element has no attributes. Its contents is plain text, containing notes for this page.

9.2.2 The <layer> element

Attributes

name
(required) Name of the layer. It must not contain white space.
edit
(optional) The value should be yes or no and indicates whether the user can select and modify the contents of the layer in the Ipe user interface (of course the user can always modify the setting of the attribute).

The layer element must be empty.

9.2.3 The <view> element

Attributes

layers
(required) The value must be a sequence of layer names defined in this page, separated by white space.
active
(required) The layer that is the active layer in this view.
effect
(optional) The symbolic name of a graphics effect to be used during the PDF page transition. The effect must be defined in the style sheet.
marked
(optional) The view is marked for printing if the value of this attribute is yes.

The view element must be empty.

ipe-7.1.4/build/doc/functions_0x6e.html0000644000175000017500000001470612120621776017572 0ustar otfriedotfried Ipelib: Class Members
Here is a list of all class members with links to the classes they belong to:

- n -


ipe-7.1.4/build/doc/manual_8.html0000644000175000017500000001037312120621776016420 0ustar otfriedotfried Ipe Manual -- 3.5 Pen, dash style, arrows, and tiling patterns
3.6 Transparency3 General Concepts3.4 Stroke and fill colors3.5 Pen, dash style, arrows, and tiling patterns

3.5 Pen, dash style, arrows, and tiling patterns

The path properties field is used to set all properties of path objects except for the pen width, which is set using the selector just above the path properties field. The dash-dot pattern (solid line, dashed, dotted etc.) effect for the boundaries of path objects, such as polygons and polygonal lines, splines, circles and ellipses, rectangles and circular arcs. It does not effect text or marks.

Line width is given in Postscript points (1/72 inch). A good value is something around 0.4 or 0.6.1

By clicking near the ends of the segment shown in the path properties field, you can toggle the front and rear arrows. Only polygonal lines, splines, and circular arcs can have arrows.

If you draw a single line segment with arrows and set it to "filled only", then the arrows will be drawn using the fill color (instead of the stroke color), and the segment is not drawn at all. This is sometimes useful to place arrows that do not appear at the end of a curve.

Various shapes and sizes of arrows are available through the context menu in the path properties field. You can add other shapes and sizes using a stylesheet.

The arrow shapes arc and farc are special. When the final segment of a path object is a circular arc, then these arcs take on a curved shape that depends on the radius of the arc. They are designed to look right even for arcs with rather small radius.

A tiling pattern allows you to hatch a path object instead of filling it with a solid color. Only path objects can be filled with a tiling pattern. The pattern defines the slope, thickness, and density of the hatching lines, their color is taken from the object's fill color. You can select a tiling pattern using the context menu in the path properties field. You can define your own tiling patterns in the documents stylesheet.

ipe-7.1.4/build/doc/ftv2vertline.png0000644000175000017500000000012612120621776017161 0ustar otfriedotfried‰PNG  IHDRɪ|IDATxíݱðøScOx@ –¨y}IEND®B`‚ipe-7.1.4/build/doc/group__ipelet.html0000644000175000017500000000646612120621776017561 0ustar otfriedotfried Ipelib: The Ipelet interface
The Ipelet interface

Classes

class  ipe::Ipelet
 Abstract base class for Ipelets. More...
class  ipe::IpeletHelper
 Service provider for Ipelets. More...

Detailed Description

Implementation of Ipe plugins.

Ipelets are dynamically loaded plugins for Ipe written in Lua.

The Ipelet class makes it easy for ipelet authors to write ipelets in C++ without using Lua's C API. They only need to provide some boilerplate Lua code to define the labels and functions of the ipelet, and use the Lua function "loadIpelet" to load a DLL containing a C++ class derived from Ipelet. The run() method of this class can then be called from Lua. The C++ code has access to services provided by Ipe through an IpeletHelper object.

Ipelet derived classes are restricted to operate on the current page of the document, and cannot modify the StyleSheet or other properties of the document. If you wish to write an ipelet doing this, you need to work in Lua (or create a C++ library using the Lua C API).


ipe-7.1.4/build/doc/classipe_1_1_bezier-members.html0000644000175000017500000001610112120621776022142 0ustar otfriedotfried Ipelib: Member List
ipe::Bezier Member List

This is the complete list of members for ipe::Bezier, including all inherited members.

approximate(double precision, std::vector< Vector > &result) const ipe::Bezier
bbox() const ipe::Bezier
Bezier()ipe::Bezierinline
Bezier(const Vector &p0, const Vector &p1, const Vector &p2, const Vector &p3)ipe::Bezierinline
closedSpline(int n, const Vector *v, std::vector< Bezier > &result)ipe::Bezierstatic
distance(const Vector &v, double bound)ipe::Bezier
intersect(const Line &l, std::vector< Vector > &result) const ipe::Bezier
intersect(const Segment &l, std::vector< Vector > &result) const ipe::Bezier
intersect(const Bezier &b, std::vector< Vector > &result) const ipe::Bezier
iVipe::Bezier
point(double t) const ipe::Bezier
quadBezier(const Vector &p0, const Vector &p1, const Vector &p2)ipe::Bezierstatic
snap(const Vector &v, double &t, Vector &pos, double &bound) const ipe::Bezier
spline(int n, const Vector *v, std::vector< Bezier > &result)ipe::Bezierstatic
straight(double precision) const ipe::Bezier
subdivide(Bezier &l, Bezier &r) const ipe::Bezier
tangent(double t) const ipe::Bezier

ipe-7.1.4/build/doc/classipe_1_1_pdf_painter.html0000644000175000017500000013663512120621776021544 0ustar otfriedotfried Ipelib: ipe::PdfPainter Class Reference

#include <ipepdfwriter.h>

Inherits ipe::Painter.

Inherited by ipe::PsPainter.

Public Member Functions

 PdfPainter (const Cascade *style, Stream &stream)
virtual ~PdfPainter ()
- Public Member Functions inherited from ipe::Painter
 Painter (const Cascade *style)
virtual ~Painter ()
void transform (const Matrix &m)
void untransform (TTransformations trans)
void translate (const Vector &v)
void push ()
void pop ()
void pushMatrix ()
void popMatrix ()
void newPath ()
void moveTo (const Vector &v)
void lineTo (const Vector &v)
void curveTo (const Vector &v1, const Vector &v2, const Vector &v3)
void curveTo (const Bezier &bezier)
void rect (const Rect &re)
void drawEllipse ()
void drawArc (const Arc &arc)
void closePath ()
void drawPath (TPathMode mode)
void drawBitmap (Bitmap bitmap)
void drawText (const Text *text)
void drawSymbol (Attribute symbol)
void addClipPath ()
void setStroke (Attribute color)
void setFill (Attribute color)
void setPen (Attribute pen)
void setDashStyle (Attribute dash)
void setLineCap (TLineCap cap)
void setLineJoin (TLineJoin join)
void setFillRule (TFillRule rule)
void setSymStroke (Attribute color)
void setSymFill (Attribute color)
void setSymPen (Attribute wid)
void setOpacity (Attribute opaq)
void setTiling (Attribute til)
void setGradient (Attribute grad)
const Cascadecascade () const
Color stroke () const
Color fill () const
const Matrixmatrix () const
Fixed pen () const
String dashStyle () const
void dashStyle (std::vector< double > &dashes, double &offset) const
TLineCap lineCap () const
TLineJoin lineJoin () const
TFillRule fillRule () const
Color symStroke () const
Color symFill () const
Fixed symPen () const
Fixed opacity () const
Attribute tiling () const
Attribute gradient () const

Static Public Member Functions

static void drawColor (Stream &stream, Color color, const char *gray, const char *rgb)

Protected Member Functions

virtual void doPush ()
virtual void doPop ()
virtual void doNewPath ()
virtual void doMoveTo (const Vector &v)
virtual void doLineTo (const Vector &v)
virtual void doCurveTo (const Vector &v1, const Vector &v2, const Vector &v3)
virtual void doClosePath ()
virtual void doDrawPath (TPathMode mode)
virtual void doDrawBitmap (Bitmap bitmap)
virtual void doDrawText (const Text *text)
virtual void doAddClipPath ()
virtual void doDrawSymbol (Attribute symbol)
void drawAttributes ()
void drawOpacity ()
- Protected Member Functions inherited from ipe::Painter
virtual void doDrawArc (const Arc &arc)
void drawArcAsBezier (double alpha)

Protected Attributes

StreamiStream
std::list< StateiActiveState
- Protected Attributes inherited from ipe::Painter
std::list< StateiState
std::list< MatrixiMatrix
const CascadeiCascade
int iInPath

Constructor & Destructor Documentation

PdfPainter::PdfPainter ( const Cascade style,
Stream stream 
)
virtual ipe::PdfPainter::~PdfPainter ( )
inlinevirtual

Member Function Documentation

void PdfPainter::drawColor ( Stream stream,
Color  color,
const char *  gray,
const char *  rgb 
)
static
void PdfPainter::doPush ( )
protectedvirtual

Perform graphics state push on output medium.

Reimplemented from ipe::Painter.

void PdfPainter::doPop ( )
protectedvirtual

Perform graphics state pop on output medium.

Reimplemented from ipe::Painter.

void PdfPainter::doNewPath ( )
protectedvirtual

Perform new path operator.

Reimplemented from ipe::Painter.

Reimplemented in ipe::PsPainter.

void PdfPainter::doMoveTo ( const Vector v)
protectedvirtual

Perform moveto operator.

The transformation matrix has already been applied.

Reimplemented from ipe::Painter.

void PdfPainter::doLineTo ( const Vector v)
protectedvirtual

Perform lineto operator.

The transformation matrix has already been applied.

Reimplemented from ipe::Painter.

void PdfPainter::doCurveTo ( const Vector v1,
const Vector v2,
const Vector v3 
)
protectedvirtual

Perform curveto operator.

The transformation matrix has already been applied.

Reimplemented from ipe::Painter.

void PdfPainter::doClosePath ( )
protectedvirtual

Perform closepath operator.

Reimplemented from ipe::Painter.

void PdfPainter::doDrawPath ( TPathMode  mode)
protectedvirtual

Actually draw the path.

Reimplemented from ipe::Painter.

Reimplemented in ipe::PsPainter.

void PdfPainter::doDrawBitmap ( Bitmap  bitmap)
protectedvirtual

Draw a bitmap.

Reimplemented from ipe::Painter.

Reimplemented in ipe::PsPainter.

void PdfPainter::doDrawText ( const Text text)
protectedvirtual

Draw a text object.

Reimplemented from ipe::Painter.

void PdfPainter::doAddClipPath ( )
protectedvirtual

Add a clip path.

Reimplemented from ipe::Painter.

Reimplemented in ipe::PsPainter.

void PdfPainter::doDrawSymbol ( Attribute  symbol)
protectedvirtual

Draw a symbol.

The default implementation calls the draw method of the object. Only PDF drawing overrides this to reuse a PDF XForm.

Reimplemented from ipe::Painter.

void PdfPainter::drawAttributes ( )
protected
void PdfPainter::drawOpacity ( )
protected

Member Data Documentation

Stream& ipe::PdfPainter::iStream
protected
std::list<State> ipe::PdfPainter::iActiveState
protected

The documentation for this class was generated from the following files:
  • ipepdfwriter.h
  • ipepdfwriter.cpp

ipe-7.1.4/build/doc/snaplines.svg0000644000175000017500000001433212120621776016542 0ustar otfriedotfried ipe-7.1.4/build/doc/classipe_1_1_shape.html0000644000175000017500000006740712120621776020351 0ustar otfriedotfried Ipelib: ipe::Shape Class Reference

#include <ipeshape.h>

Classes

struct  Imp

Public Member Functions

 Shape ()
 Shape (const Rect &rect)
 Shape (const Segment &seg)
 Shape (const Vector &center, double radius)
 Shape (const Vector &center, double radius, double alpha0, double alpha1)
 ~Shape ()
 Shape (const Shape &rhs)
Shapeoperator= (const Shape &rhs)
bool load (String data)
void save (Stream &stream) const
void addToBBox (Rect &box, const Matrix &m, bool cp) const
double distance (const Vector &v, const Matrix &m, double bound) const
void snapVtx (const Vector &mouse, const Matrix &m, Vector &pos, double &bound) const
void snapBnd (const Vector &mouse, const Matrix &m, Vector &pos, double &bound) const
int countSubPaths () const
const SubPathsubPath (int i) const
bool isSegment () const
void appendSubPath (SubPath *sp)
void draw (Painter &painter) const

Detailed Description

A geometric shape, consisting of several (open or closed) subpaths.

This class represents vector graphics geometry following the PDF "path", but is actually a bit more complicated since we add new subtypes: arcs, parabolas, uniform B-splines (in PDF, all of these are converted to cubic Bezier splines).

A Shape consists of a set of subpaths (SubPath), each of which is either open or closed, and which are rendered by stroking and filling as a whole. The distinction between open and closed is meaningful for stroking only, for filling any open subpath is implicitely closed. Stroking a set of subpaths is identical to stroking them individually. This is not true for filling: using several subpaths, one can construct objects with holes, and more complicated pattern.

A subpath is either an Ellipse (a complete, closed ellipse), a ClosedSpline (a closed uniform B-spline curve), or a Curve. A curve consists of a sequence of segments. Segments are either straight, a quadratic Bezier spline, a cubic Bezier spline, an elliptic arc, or a uniform cubic B-spline.

Shape is implemented using reference counting and can be copied and passed by value efficiently. The only mutator methods are appendSubPath() and load(), which can only be called during construction of the Shape (that is, before its implementation has been shared).

Constructor & Destructor Documentation

Shape::Shape ( )

Construct an empty shape (zero subpaths).

Shape::Shape ( const Rect rect)
explicit

Convenience function: create a rectangle shape.

Shape::Shape ( const Segment seg)
explicit

Convenience function: create a single line segment.

Shape::Shape ( const Vector center,
double  radius 
)
explicit

Convenience function: create circle with center and radius.

Shape::Shape ( const Vector center,
double  radius,
double  alpha0,
double  alpha1 
)
explicit

Convenience function: create circular arc.

If alpha1 is larger than alpha0, the arc is oriented positively, otherwise negatively.

Shape::~Shape ( )

Destructor (takes care of reference counting).

Shape::Shape ( const Shape rhs)

Copy constructor (constant time).

Member Function Documentation

Shape & Shape::operator= ( const Shape rhs)

Assignment operator (constant-time).

bool Shape::load ( String  data)

Create a Shape from XML data.

Appends subpaths from XML data to the current Shape. Returns false if the path syntax is incorrect (the Shape will be in an inconsistent state and must be discarded).

This method can only be used during construction of the Shape. It will panic if the implementation has been shared.

void Shape::save ( Stream stream) const

Save Shape onto XML stream.

void Shape::addToBBox ( Rect box,
const Matrix m,
bool  cp 
) const

Add shape (transformed by m) to box.

double Shape::distance ( const Vector v,
const Matrix m,
double  bound 
) const
void Shape::snapVtx ( const Vector mouse,
const Matrix m,
Vector pos,
double &  bound 
) const
void Shape::snapBnd ( const Vector mouse,
const Matrix m,
Vector pos,
double &  bound 
) const
int ipe::Shape::countSubPaths ( ) const
inline

Return number of subpaths.

const SubPath* ipe::Shape::subPath ( int  i) const
inline

Return subpath.

bool Shape::isSegment ( ) const

Is this Shape a single straight segment?

void Shape::appendSubPath ( SubPath sp)

Append a SubPath to shape.

The Shape will take ownership of the subpath. This method can only be used during construction of the Shape. It will panic if the implementation has been shared.

void Shape::draw ( Painter painter) const

Draw the Shape as a path to painter.

Does not call newPath() on painter.


The documentation for this class was generated from the following files:
  • ipeshape.h
  • ipeshape.cpp

ipe-7.1.4/build/doc/manual_36.html0000644000175000017500000000527312120621776016504 0ustar otfriedotfried Ipe Manual -- 8.2 Writing ipelets
8.3 Troubleshooting the LaTeX-conversion8 Advanced topics8.1 Sharing Latex definitions with your Latex document8.2 Writing ipelets

8.2 Writing ipelets

An ipelet is an extension to Ipe. Ipe 7 uses the scripting language Lua (in fact, most of the Ipe program itself is written in Lua), and loads ipelets written in Lua when it starts up. It is also possible to write ipelets in C++, using a small Lua wrapper that declares the methods available inside the ipelet.

Documentation about writing ipelets can be found in the Ipelib documentation.

ipe-7.1.4/build/doc/manual_ipe6_to_ipe7.html0000644000175000017500000001724312120621776020545 0ustar otfriedotfried Ipe Manual -- 10 If you have used Ipe 6 before
11 Using Ipe figures in LatexTop9 The Ipe file format10 If you have used Ipe 6 before

10 If you have used Ipe 6 before

Ipe 7 is not very different from Ipe 6 for the casual user, but there are a number of changes you need to be aware of.

File format.

First of all, the file format of Ipe 7 is different, and Ipe 7 cannot open files created by Ipe 6. To reuse an Ipe 6 document in EPS or PDF format, you first need to run the new tool "ipeextract", which will extract the XML stream inside the document and save it as an XML file. An Ipe 6 XML document can then be converted to Ipe 7 format using "ipe6upgrade".

If your figure is figure.pdf, then the command

ipeextract figure.pdf
will save the XML stream as figure.xml. Then run
ipe6upgrade figure.xml
which will save your document in Ipe 7 format as figure.ipe. All contents of the original document should have been preserved.

Shortcuts.

The keyboard shortcuts of a small number of commands have changed. Check the menu to find out what changes were made. (You can undo these changes by customizing Ipe.)

The mouse shortcuts have changed as well. The right button now opens the context menu. The middle button is only used for pan, because it seems hard to use a scroll wheel for anything else. Select, translate, rotate, scale, and stretch are still available by holding Control or Alt when pressing a mouse button.

Absolute attributes.

The user interface no longer switches between displaying symbolic and absolute attribute values. To select an absolute color, pen width, text or mark size, press the little button to the left of the selector box.

Void color and pen.

There is no longer a void color for filling, or a void pen for stroking. For each path object, you indicate whether you want it to be stroked, filled, or both. This setting is independent of the stroke and fill color attribute setting. Unlike in Ipe 6, it is no longer possible to have path objects that are neither stroked nor filled (such an object would now be stroked in black).

Path properties.

Except for the pen width, path properties are now set in the path property box (below the pen width). Clicking near the ends of the segment turns arrows on and off, clicking at the right end will cycle through the modes "stroke", "stroke & fill", and "fill." The right mouse button will open a context menu that gives you access to all other settings, including the new arrow shape menu, and the new tiling menu. A tiling will hatch the object with a line pattern, but only if is filled. You can define your own arrow shapes and tiling patterns using a stylesheet.

Ink tool.

There is a new tool (the one with the brush icon) for drawing path objects using a pen on a tablet PC.

Page transition effects.

These now need to be defined in the stylesheet.

Ipetopng replaced by iperender.

The program "ipetopng" was replaced by a new tool "iperender," which can render Ipe documents to PNG or SVG format. The latter is very nice for including scalable figures in web pages.

Customization.

The Preferences dialog has disappeared entirely. Ipe 7 can only be customized by editing configuration files written in Lua.

Mark objects.

Mark objects are now simply symbols defined in a style sheet—there is no actual mark object anymore. Nevertheless, the user interface allows you to use them as in Ipe 6, with the added benefit that you can define your own mark shapes.

Clipping paths.

It is now possible to add a clipping path to a group object. The group will only be drawn inside this clipping path.

Transparency.

Ipe now supports transparency for text objects and path objects. This feature is not available unless it is enabled in a stylesheet.

Presentations.

To make cooler presentations, Ipe now supports gradients (so you can draw glassy balls), and it is possible to use arbitrary Ipe objects as the "bullet" in itemize environments.

Images on the screen.

Images are no longer shown with reduced resolution on the screen. Cairo can handle images fast enough to make this unnecessary.

Bounding boxes.

When a page has several views, Ipe will now compute the same bounding box for each view of the page. This is what you need when you make an animated figure consisting of several views, for instance for use from the "beamer" package.

If you need to force a larger bounding box, you can do so by drawing a rectangle in a layer named "BBOX" and making that layer invisible. (This specially named layer will be included in the bounding box calculation even if it is not visible in any view.)

If you do need independent bounding boxes for each view (as in Ipe 6), create a layer named "VIEWBBOX". Any view in which this layer is visible will receive a bounding box computed for the objects visible in this view only.

To crop or not to crop.

In Ipe 6, use of the PDF CropBox was set in the document properties. In Ipe 7 it is determined by the layout set in the stylesheet (and should therefore always be right).
ipe-7.1.4/build/doc/classipe_1_1_angle-members.html0000644000175000017500000001011512120621776021747 0ustar otfriedotfried Ipelib: Member List
ipe::Angle Member List

This is the complete list of members for ipe::Angle, including all inherited members.

Angle()ipe::Angleinlineexplicit
Angle(double alpha)ipe::Angleinline
degrees() const ipe::Angle
Degrees(double alpha)ipe::Angleinlinestatic
liesBetween(Angle small, Angle large) const ipe::Angle
normalize(double lowlimit)ipe::Angle
operator double() const ipe::Angleinline

ipe-7.1.4/build/doc/classipe_1_1_b_box_painter.html0000644000175000017500000012010312120621776022043 0ustar otfriedotfried Ipelib: ipe::BBoxPainter Class Reference

#include <ipeutils.h>

Inherits ipe::Painter.

Public Member Functions

 BBoxPainter (const Cascade *style)
Rect bbox () const
- Public Member Functions inherited from ipe::Painter
 Painter (const Cascade *style)
virtual ~Painter ()
void transform (const Matrix &m)
void untransform (TTransformations trans)
void translate (const Vector &v)
void push ()
void pop ()
void pushMatrix ()
void popMatrix ()
void newPath ()
void moveTo (const Vector &v)
void lineTo (const Vector &v)
void curveTo (const Vector &v1, const Vector &v2, const Vector &v3)
void curveTo (const Bezier &bezier)
void rect (const Rect &re)
void drawEllipse ()
void drawArc (const Arc &arc)
void closePath ()
void drawPath (TPathMode mode)
void drawBitmap (Bitmap bitmap)
void drawText (const Text *text)
void drawSymbol (Attribute symbol)
void addClipPath ()
void setStroke (Attribute color)
void setFill (Attribute color)
void setPen (Attribute pen)
void setDashStyle (Attribute dash)
void setLineCap (TLineCap cap)
void setLineJoin (TLineJoin join)
void setFillRule (TFillRule rule)
void setSymStroke (Attribute color)
void setSymFill (Attribute color)
void setSymPen (Attribute wid)
void setOpacity (Attribute opaq)
void setTiling (Attribute til)
void setGradient (Attribute grad)
const Cascadecascade () const
Color stroke () const
Color fill () const
const Matrixmatrix () const
Fixed pen () const
String dashStyle () const
void dashStyle (std::vector< double > &dashes, double &offset) const
TLineCap lineCap () const
TLineJoin lineJoin () const
TFillRule fillRule () const
Color symStroke () const
Color symFill () const
Fixed symPen () const
Fixed opacity () const
Attribute tiling () const
Attribute gradient () const

Protected Member Functions

virtual void doPush ()
virtual void doPop ()
virtual void doNewPath ()
virtual void doMoveTo (const Vector &v)
virtual void doLineTo (const Vector &v)
virtual void doCurveTo (const Vector &v1, const Vector &v2, const Vector &v3)
virtual void doDrawPath (TPathMode mode)
virtual void doDrawBitmap (Bitmap bitmap)
virtual void doDrawText (const Text *text)
virtual void doAddClipPath ()
- Protected Member Functions inherited from ipe::Painter
virtual void doDrawArc (const Arc &arc)
virtual void doClosePath ()
virtual void doDrawSymbol (Attribute symbol)
void drawArcAsBezier (double alpha)

Additional Inherited Members

- Protected Attributes inherited from ipe::Painter
std::list< StateiState
std::list< MatrixiMatrix
const CascadeiCascade
int iInPath

Detailed Description

Paint objects using this painter to compute an accurate bounding box.

The Object::bbox member function computes a bounding box useful for distance calculations and optimizations. To find a bounding box that is accurate for the actual drawn object, paint the object using a BBoxPainter, and retrieve the box with bbox.

Constructor & Destructor Documentation

BBoxPainter::BBoxPainter ( const Cascade style)

Member Function Documentation

Rect ipe::BBoxPainter::bbox ( ) const
inline
void BBoxPainter::doPush ( )
protectedvirtual

Perform graphics state push on output medium.

Reimplemented from ipe::Painter.

void BBoxPainter::doPop ( )
protectedvirtual

Perform graphics state pop on output medium.

Reimplemented from ipe::Painter.

void BBoxPainter::doNewPath ( )
protectedvirtual

Perform new path operator.

Reimplemented from ipe::Painter.

void BBoxPainter::doMoveTo ( const Vector v)
protectedvirtual

Perform moveto operator.

The transformation matrix has already been applied.

Reimplemented from ipe::Painter.

void BBoxPainter::doLineTo ( const Vector v)
protectedvirtual

Perform lineto operator.

The transformation matrix has already been applied.

Reimplemented from ipe::Painter.

void BBoxPainter::doCurveTo ( const Vector v1,
const Vector v2,
const Vector v3 
)
protectedvirtual

Perform curveto operator.

The transformation matrix has already been applied.

Reimplemented from ipe::Painter.

void BBoxPainter::doDrawPath ( TPathMode  mode)
protectedvirtual

Actually draw the path.

Reimplemented from ipe::Painter.

void BBoxPainter::doDrawBitmap ( Bitmap  bitmap)
protectedvirtual

Draw a bitmap.

Reimplemented from ipe::Painter.

void BBoxPainter::doDrawText ( const Text text)
protectedvirtual

Draw a text object.

Reimplemented from ipe::Painter.

void BBoxPainter::doAddClipPath ( )
protectedvirtual

Add a clip path.

Reimplemented from ipe::Painter.


The documentation for this class was generated from the following files:
  • ipeutils.h
  • ipeutils.cpp

ipe-7.1.4/build/doc/functions_func_0x72.html0000644000175000017500000001731412120621776020521 0ustar otfriedotfried Ipelib: Class Members - Functions
 

- r -


ipe-7.1.4/build/doc/ftv2mo.png0000644000175000017500000000062312120621776015746 0ustar otfriedotfried‰PNG  IHDRÚ}\ˆZIDATxí1Kû@ÆiƒØB…Ò¡(h¬"EÄI'ÁoàªèÚ©ßÀáâä 8ùçR-‚â B«TPˆï]z¥B’3 _Þã’»ç}ŸË]VÇ÷}€ÌÈdIæ®i쟯JØ–b¸šÍÃõ+º™|KÂ…°,[Pï\ʘMÆ¢#€ä…F`JݤìÛk³úA±àþè?ØY4ck6"¹Z)ê¸0SHM¨@ï㋺WÖmo¼4èHJ¨Àÿö+…QobŒút ¤ú’*Ð~êè8_+3Y-ñðÜå½÷ ˜PwA¶+^ý}ºì£+xìhÏ•MAE]€TD~EÞߴ^R)`ÖAùŸÏ9©pÔq-Û¾õÛ3tÝÊÆ›ˆÃTÐHÈ)€ ½Š’ICªxëd#1ôú§é€ m@Vüý?Zæßgo_½3-³\IEND®B`‚ipe-7.1.4/build/doc/manual_34.html0000644000175000017500000000503612120621776016477 0ustar otfriedotfried Ipe Manual -- 8 Advanced topics ipe-7.1.4/build/doc/classipe_1_1_canvas.html0000644000175000017500000013703712120621776020521 0ustar otfriedotfried Ipelib: ipe::Canvas Class Reference

#include <ipecanvas_win.h>

Inherits ipe::CanvasBase, ipe::CanvasBase, and ipe::CanvasBase.

Public Member Functions

 Canvas (GtkWidget *parent)
 ~Canvas ()
GtkWidget * window () const
 Canvas (QWidget *parent, Qt::WFlags f=0)
virtual void setCursor (TCursor cursor, double w=1.0, Color *color=0)
 Canvas (HWND parent)
HWND windowId () const
- Public Member Functions inherited from ipe::CanvasBase
virtual ~CanvasBase ()
void setPage (const Page *page, int pno, int view, const Cascade *sheet)
void setFontPool (const FontPool *fontPool)
Vector pan () const
double zoom () const
const Cascadecascade () const
Vector center () const
Vector pos () const
Vector unsnappedPos () const
Vector globalPos () const
Vector simpleSnapPos () const
const Snapsnap () const
int additionalModifiers () const
void setAdditionalModifiers (int mod)
Vector devToUser (const Vector &arg) const
Vector userToDev (const Vector &arg) const
void setCanvasStyle (const Style &style)
Style canvasStyle () const
void setPan (const Vector &v)
void setZoom (double zoom)
void setSnap (const Snap &s)
void setDimmed (bool dimmed)
void setAutoOrigin (const Vector &v)
Matrix canvasTfm () const
void setObserver (CanvasObserver *observer)
void setFifiVisible (bool visible)
void setSelectionVisible (bool visible)
void setTool (Tool *tool)
void finishTool ()
void update ()
void updateTool ()
int canvasWidth () const
int canvasHeight () const

Static Public Member Functions

static void init (HINSTANCE hInstance)

Protected Member Functions

virtual void invalidate ()
virtual void invalidate (int x, int y, int w, int h)
virtual void paintEvent (QPaintEvent *ev)
virtual void mousePressEvent (QMouseEvent *ev)
virtual void mouseReleaseEvent (QMouseEvent *ev)
virtual void mouseMoveEvent (QMouseEvent *ev)
virtual void tabletEvent (QTabletEvent *ev)
virtual void wheelEvent (QWheelEvent *ev)
virtual void keyPressEvent (QKeyEvent *ev)
virtual QSize sizeHint () const
- Protected Member Functions inherited from ipe::CanvasBase
 CanvasBase ()
void drawPaper (cairo_t *cc)
void drawFrame (cairo_t *cc)
void drawAxes (cairo_t *cc)
void drawGrid (cairo_t *cc)
void drawObjects (cairo_t *cc)
void drawTool (Painter &painter)
bool snapToPaperAndFrame ()
void refreshSurface ()
void computeFifi (double x, double y)

Additional Inherited Members

- Public Types inherited from ipe::CanvasBase
enum  TModifiers { EShift = 0x100, EControl = 0x200, EAlt = 0x400, EMeta = 0x800 }
enum  TCursor { EStandardCursor, EHandCursor, ECrossCursor, EDotCursor }
- Protected Attributes inherited from ipe::CanvasBase
CanvasObserveriObserver
TooliTool
const PageiPage
int iPageNumber
int iView
const CascadeiCascade
Style iStyle
Vector iPan
double iZoom
Snap iSnap
bool iDimmed
bool iAutoSnap
Vector iAutoOrigin
int iAdditionalModifiers
bool iRepaintObjects
int iWidth
int iHeight
cairo_surface_t * iSurface
Vector iUnsnappedMousePos
Vector iMousePos
Vector iGlobalPos
Vector iOldFifi
bool iFifiVisible
bool iSelectionVisible
FontsiFonts

Detailed Description

A widget (control) that displays an Ipe document page.

Constructor & Destructor Documentation

Canvas::Canvas ( GtkWidget *  parent)
Canvas::~Canvas ( )
Canvas::Canvas ( QWidget *  parent,
Qt::WFlags  f = 0 
)

Construct a new canvas.

Canvas::Canvas ( HWND  parent)

Member Function Documentation

GtkWidget* ipe::Canvas::window ( ) const
inline
virtual void ipe::Canvas::setCursor ( TCursor  cursor,
double  w = 1.0,
Color color = 0 
)
virtual

Implements ipe::CanvasBase.

virtual void ipe::Canvas::invalidate ( )
protectedvirtual

Implements ipe::CanvasBase.

virtual void ipe::Canvas::invalidate ( int  x,
int  y,
int  w,
int  h 
)
protectedvirtual

Implements ipe::CanvasBase.

void Canvas::paintEvent ( QPaintEvent *  ev)
protectedvirtual
void Canvas::mousePressEvent ( QMouseEvent *  ev)
protectedvirtual
void Canvas::mouseReleaseEvent ( QMouseEvent *  ev)
protectedvirtual
void Canvas::mouseMoveEvent ( QMouseEvent *  ev)
protectedvirtual
void Canvas::tabletEvent ( QTabletEvent *  ev)
protectedvirtual
void Canvas::wheelEvent ( QWheelEvent *  ev)
protectedvirtual
void Canvas::keyPressEvent ( QKeyEvent *  ev)
protectedvirtual
QSize Canvas::sizeHint ( ) const
protectedvirtual
void Canvas::init ( HINSTANCE  hInstance)
static
HWND ipe::Canvas::windowId ( ) const
inline

The documentation for this class was generated from the following files:
  • ipecanvas_gtk.h
  • ipecanvas_win.h
  • ipecanvas_qt.h
  • ipecanvas_gtk.cpp
  • ipecanvas_qt.cpp
  • ipecanvas_win.cpp

ipe-7.1.4/build/doc/structipe_1_1_painter_1_1_state-members.html0000644000175000017500000001335612120621776024414 0ustar otfriedotfried Ipelib: Member List
ipe::Painter::State Member List

ipe-7.1.4/build/doc/classipe_1_1_pdf_number-members.html0000644000175000017500000001352312120621776023010 0ustar otfriedotfried Ipelib: Member List
ipe::PdfNumber Member List

This is the complete list of members for ipe::PdfNumber, including all inherited members.

array() const ipe::PdfObjvirtual
boolean() const ipe::PdfObjvirtual
dict() const ipe::PdfObjvirtual
name() const ipe::PdfObjvirtual
null() const ipe::PdfObjvirtual
number() const ipe::PdfNumbervirtual
PdfNumber(double val)ipe::PdfNumberinlineexplicit
ref() const ipe::PdfObjvirtual
repr() const ipe::PdfObj
string() const ipe::PdfObjvirtual
value() const ipe::PdfNumberinline
write(Stream &stream) const ipe::PdfNumbervirtual
~PdfObj()=0ipe::PdfObjpure virtual

ipe-7.1.4/build/doc/structipe_1_1_select_tool_1_1_s_obj-members.html0000644000175000017500000000553012120621776025235 0ustar otfriedotfried Ipelib: Member List
ipe::SelectTool::SObj Member List

This is the complete list of members for ipe::SelectTool::SObj, including all inherited members.

distanceipe::SelectTool::SObj
indexipe::SelectTool::SObj

ipe-7.1.4/build/doc/group__obj.html0000644000175000017500000001010612120621776017033 0ustar otfriedotfried Ipelib: Ipe Objects
Ipe Objects

Classes

class  ipe::Group
 The group object. More...
class  ipe::Image
 The image object. More...
class  ipe::Object
 Base class for all Ipe objects, composite or leaf. More...
class  ipe::Path
 The path object (polylines, polygons, and generalizations). More...
class  ipe::Reference
 The reference object. More...
class  ipe::Text
 The text object. More...

Detailed Description

The Ipe object model.

This module deals with the actual objects inside an Ipe document. All Ipe objects are derived from Object.


ipe-7.1.4/build/doc/classipe_1_1_bezier.html0000644000175000017500000006461412120621776020526 0ustar otfriedotfried Ipelib: ipe::Bezier Class Reference

#include <ipegeo.h>

Public Member Functions

 Bezier ()
 Bezier (const Vector &p0, const Vector &p1, const Vector &p2, const Vector &p3)
Vector point (double t) const
Vector tangent (double t) const
double distance (const Vector &v, double bound)
bool straight (double precision) const
void subdivide (Bezier &l, Bezier &r) const
void approximate (double precision, std::vector< Vector > &result) const
Rect bbox () const
bool snap (const Vector &v, double &t, Vector &pos, double &bound) const
void intersect (const Line &l, std::vector< Vector > &result) const
void intersect (const Segment &l, std::vector< Vector > &result) const
void intersect (const Bezier &b, std::vector< Vector > &result) const

Static Public Member Functions

static Bezier quadBezier (const Vector &p0, const Vector &p1, const Vector &p2)
static void spline (int n, const Vector *v, std::vector< Bezier > &result)
static void closedSpline (int n, const Vector *v, std::vector< Bezier > &result)

Public Attributes

Vector iV [4]

Detailed Description

A cubic Bezier spline.

Constructor & Destructor Documentation

ipe::Bezier::Bezier ( )
inline

Default constructor, uninitialized curve.

ipe::Bezier::Bezier ( const Vector p0,
const Vector p1,
const Vector p2,
const Vector p3 
)
inline

Constructor with four control points.

Member Function Documentation

Vector Bezier::point ( double  t) const

Return point on curve with parameter t (from 0.0 to 1.0).

Vector Bezier::tangent ( double  t) const

Return tangent direction of curve at parameter t (from 0.0 to 1.0).

The returned vector is not normalized.

double Bezier::distance ( const Vector v,
double  bound 
)

Return distance to Bezier spline.

But may just return bound if actual distance is larger. The Bezier spline is approximated to a precision of 1.0, and the distance to the approximation is returned.

bool Bezier::straight ( double  precision) const

Returns true if the Bezier curve is nearly identical to the line segment iV[0]..iV[3].

void Bezier::subdivide ( Bezier l,
Bezier r 
) const

Subdivide this Bezier curve in the middle.

void Bezier::approximate ( double  precision,
std::vector< Vector > &  result 
) const

Approximate by a polygonal chain.

result must be empty when calling this.

Rect Bezier::bbox ( ) const

Return a tight bounding box (accurate to within 0.5).

bool Bezier::snap ( const Vector v,
double &  t,
Vector pos,
double &  bound 
) const

Find (approximately) nearest point on Bezier spline.

Find point on spline nearest to v, but only if it is closer than bound. If a point is found, sets t to the parameter value and pos to the actual point, and returns true.

Bezier Bezier::quadBezier ( const Vector p0,
const Vector p1,
const Vector p2 
)
static

Convert a quadratic Bezier-spline to a cubic one.

The quadratic Bezier-spline with control points p0, p1, p2 is identical to the cubic Bezier-spline with control points q0 = p0, q1 = (2p1 + p0)/3, q2 = (2p1 + p2)/3, q3 = p2.

void Bezier::spline ( int  n,
const Vector v,
std::vector< Bezier > &  result 
)
static

Convert a uniform cubic B-spline to a series of Bezier splines.

First and last control point are given multiplicity 3. Bezier splines are appended to result.

void Bezier::closedSpline ( int  n,
const Vector v,
std::vector< Bezier > &  result 
)
static

Convert a closed uniform cubic B-spline to a series of Bezier splines.

Bezier splines are appended to result.

void Bezier::intersect ( const Line l,
std::vector< Vector > &  result 
) const

Compute intersection points of Bezier with Line.

void Bezier::intersect ( const Segment l,
std::vector< Vector > &  result 
) const

Compute intersection points of Bezier with Segment.

void Bezier::intersect ( const Bezier b,
std::vector< Vector > &  result 
) const

Compute intersection points of Bezier with Bezier.

Member Data Documentation

Vector ipe::Bezier::iV[4]

The documentation for this class was generated from the following files:
  • ipegeo.h
  • ipegeo.cpp

ipe-7.1.4/build/doc/classipe_1_1_pdf_string.html0000644000175000017500000002520712120621776021400 0ustar otfriedotfried Ipelib: ipe::PdfString Class Reference
ipe::PdfString Class Reference

#include <ipepdfparser.h>

Inherits ipe::PdfObj.

Public Member Functions

 PdfString (const String &val)
virtual const PdfStringstring () const
virtual void write (Stream &stream) const
String value () const
- Public Member Functions inherited from ipe::PdfObj
virtual ~PdfObj ()=0
virtual const PdfNullnull () const
virtual const PdfBoolboolean () const
virtual const PdfNumbernumber () const
virtual const PdfNamename () const
virtual const PdfRefref () const
virtual const PdfArrayarray () const
virtual const PdfDictdict () const
String repr () const

Detailed Description

The PDF string object.

Constructor & Destructor Documentation

ipe::PdfString::PdfString ( const String val)
inlineexplicit

Member Function Documentation

const PdfString * PdfString::string ( ) const
virtual

Return this object as PDF string object.

Reimplemented from ipe::PdfObj.

void PdfString::write ( Stream stream) const
virtual

Implements ipe::PdfObj.

String ipe::PdfString::value ( ) const
inline

The documentation for this class was generated from the following files:
  • ipepdfparser.h
  • ipepdfparser.cpp

ipe-7.1.4/build/doc/classipe_1_1_iml_parser.html0000644000175000017500000005357512120621776021407 0ustar otfriedotfried Ipelib: ipe::ImlParser Class Reference

#include <ipeiml.h>

Inherits ipe::XmlParser.

Inherited by PdfStreamParser, and PsStreamParser.

Public Types

enum  Errors { ESuccess = 0, EVersionTooOld, EVersionTooRecent, ESyntaxError }

Public Member Functions

 ImlParser (DataSource &source)
int parseDocument (Document &doc)
bool parsePage (Page &page)
ObjectparseObject (String tag, Page *page=0, int *currentLayer=0)
StyleSheetparseStyleSheet ()
bool parseStyle (StyleSheet &sheet)
PageparsePageSelection ()
virtual Buffer pdfStream (int objNum)
bool parseBitmap ()
bool parseFontmap (String *stdNames, String *paths)
- Public Member Functions inherited from ipe::XmlParser
 XmlParser (DataSource &source)
virtual ~XmlParser ()
int parsePosition () const
String parseToTag ()
bool parseAttributes (XmlAttributes &attr, bool qm=false)
bool parsePCDATA (String tag, String &pcdata)
bool isTagChar (int ch)
void getChar ()
bool eos ()
void skipWhitespace ()

Additional Inherited Members

- Protected Member Functions inherited from ipe::XmlParser
String parseToTagX ()
- Protected Attributes inherited from ipe::XmlParser
DataSourceiSource
String iTopElement
int iCh
int iPos

Detailed Description

XML Parser for Ipe documents and style sheets.

A recursive descent parser for the XML streams.

After experimenting with various XML parsing frameworks, this turned out to work best for Ipe.

Member Enumeration Documentation

Enumerator:
ESuccess 
EVersionTooOld 
EVersionTooRecent 
ESyntaxError 

Constructor & Destructor Documentation

ImlParser::ImlParser ( DataSource source)
explicit

Member Function Documentation

int ImlParser::parseDocument ( Document doc)

Read a complete document from IML stream.

Returns an error code.

bool ImlParser::parsePage ( Page page)

Parse an Page.

On calling, stream must be just past page.

Object * ImlParser::parseObject ( String  tag,
Page page = 0,
int *  currentLayer = 0 
)

parse an Object.

On calling, stream must be just past the tag.

StyleSheet * ImlParser::parseStyleSheet ( )

parse a complete style sheet.

On calling, stream must be before the 'ipestyle' tag. A <?xml> tag is allowed.

bool ImlParser::parseStyle ( StyleSheet sheet)

Parse a style sheet.

On calling, stream must be just past the style tag.

Page * ImlParser::parsePageSelection ( )

parse an <ipepage> element (used on clipboard).

Buffer ImlParser::pdfStream ( int  objNum)
virtual

XML contents can refer to data in PDF.

If the XML stream is embedded in a PDF file, XML contents can refer to PDF objects. A derived parser must implement this method to access PDF data.

It is assumed that PDF object objNum is a stream. Its contents (uncompressed!) is returned in a buffer.

bool ImlParser::parseBitmap ( )

Parse an Bitmap.

On calling, stream must be just past bitmap.

bool ipe::ImlParser::parseFontmap ( String stdNames,
String paths 
)

The documentation for this class was generated from the following files:
  • ipeiml.h
  • ipeiml.cpp

ipe-7.1.4/build/doc/structipe_1_1_symbol.html0000644000175000017500000002165412120621776020767 0ustar otfriedotfried Ipelib: ipe::Symbol Class Reference

#include <ipestyle.h>

Public Member Functions

 Symbol ()
 Symbol (Object *object)
 Symbol (const Symbol &rhs)
Symboloperator= (const Symbol &rhs)
 ~Symbol ()

Public Attributes

bool iXForm
TTransformations iTransformations
ObjectiObject

Detailed Description

A symbol is a named object defined in an ipe::StyleSheet.

Constructor & Destructor Documentation

Symbol::Symbol ( )

Default constructor.

Symbol::Symbol ( Object object)

Create symbol for object (takes ownership).

Symbol::Symbol ( const Symbol rhs)

Copy constructor.

Symbol::~Symbol ( )

Destructor.

Member Function Documentation

Symbol & Symbol::operator= ( const Symbol rhs)

Assignment operator.

Member Data Documentation

bool ipe::Symbol::iXForm
TTransformations ipe::Symbol::iTransformations
Object* ipe::Symbol::iObject

The documentation for this class was generated from the following files:
  • ipestyle.h
  • ipestyle.cpp

ipe-7.1.4/build/doc/manual_14.html0000644000175000017500000001004712120621776016473 0ustar otfriedotfried Ipe Manual -- 3.11 Mouse shortcuts
3 General Concepts3.10 Layers3.11 Mouse shortcuts

3.11 Mouse shortcuts

For the beginner, choosing a selection or transformation mode and working with the left mouse button is easiest. Frequent Ipe users don't mind to remember the following shortcuts, as they allow you to perform selections and transformations without leaving the current mode:

Left Mouse Right mouse
Plain (*) context menu
Shift (*) pan
Ctrl select stretch
Ctrl+Shift select non-destructively scale
Alt translate rotate
Alt+Shift translate horizontal/vertical rotate

The fields marked (*) depend on the current mode.

The middle mouse button always pans the canvas. The right mouse button brings up the object context menu.

If you have to use Ipe with a two-button mouse, where you would normally use the middle mouse button (for instance, to move a vertex when editing a path object), you can hold the Shift-key and use the right mouse button.

If you are not happy with these shortcuts, they can be changed easily.

ipe-7.1.4/build/doc/manual_42.html0000644000175000017500000001606612120621776016503 0ustar otfriedotfried Ipe Manual -- 9.1 The <ipe> element
9.2 The <page> element9 The Ipe file format9.1 The <ipe> element

9.1 The <ipe> element

Attributes

version
(required) The value (a number, e.g. 70103 for Ipelib 7.1.3) indicates the earliest Ipelib version that can interpret the document. Ipe will refuse to load documents that require a version larger than its own, and may refuse to load documents that are too old (and which will have to be converted using a separate program).
creator
(optional) indicates the program that created the file and is not interpreted by Ipe at all.

Contents

  1. An <info> element (optional),
  2. a <preamble> element (optional),
  3. a series of <bitmap> and <ipestyle> elements (optional),
  4. a series of page elements.

The <ipestyle> elements form a "cascade", with the last <ipestyle> element becoming the top-level style sheet. When symbolic names are looked up, the style sheets are checked from top to bottom. Ipe always appends the built-in standard style sheet at the bottom of the stack.

9.1.1 The <info> element

Attributes

title
(optional) document title,
author
(optional) document author,
subject
(optional) document subject,
keywords
(optional) document keywords,
pagemode
(optional) the only value understood by Ipe is fullscreen, which causes the document to be opened in full screen mode in PDF readers.
created
(optional) creation time in PDF format, e.g. "D:20030127204100".
modified
(optional) modification time in PDF format,
numberpages
(optional) if the value is yes, then Ipe will save PDF documents with visible page numbers on each page.

This element must be empty.

9.1.2 The <preamble> element

The contents of this element is LaTeX source code, to be used as the LaTeX preamble when running LaTeX to process the text objects in the document. It should not contain a \documentclass command, but can contain \usepackage commands and macro definitions.

The <preamble> element has an optional attribute encoding. If this is set, the LaTeX file created for the conversion of text objects is converted to this encoding.

9.1.3 The <bitmap> element

Each <bitmap> element defines a bitmap to be used by <image> objects.

Attributes

id
(required) the value must be an integer that will define the bitmap throughout the Ipe document,
width
(required) integer width in pixels,
height
(required) integer height in pixels,
ColorSpace
(required) possible values are "DeviceGray", "DeviceRGB", and "DeviceCMYK",
BitsPerComponent
(required) value must be 8,
ColorKey
(optional) an RGB color in hexadecimal, indicating the transparent color (only suppored for "DeviceRGB" color space),
length
(required unless there is no filter) the number of bytes of image data,
Filter
(optional) possible values are "FlateDecode" or "DCTDecode" to indicate a compressed image (the latter is used for JPEG images).
encoding
(optional) possible value is "base64" to indicate that the image data is base64-encoded (not in hexadecimal).

The contents of the <bitmap> element is the image data, either base64-encoded or in hexadecimal format. White space between bytes is ignored. If no filter is specified, pixels are stored row by row, with rows padded to a full byte boundary.

Note that images with color maps are not supported, and such support is not planned. (The Insert image ipelet does allow you to insert images with color maps, but they are stored as 24-bit images. Since the data is compressed, this does not seriously increase the image data size.)

ipe-7.1.4/build/doc/functions_func_0x74.html0000644000175000017500000002331712120621776020523 0ustar otfriedotfried Ipelib: Class Members - Functions
 

- t -


ipe-7.1.4/build/doc/classipe_1_1_buffer-members.html0000644000175000017500000001214112120621776022133 0ustar otfriedotfried Ipelib: Member List
ipe::Buffer Member List

This is the complete list of members for ipe::Buffer, including all inherited members.

Buffer()ipe::Buffer
Buffer(const Buffer &rhs)ipe::Buffer
Buffer(int size)ipe::Bufferexplicit
Buffer(const char *data, int size)ipe::Bufferexplicit
data()ipe::Bufferinline
data() const ipe::Bufferinline
operator=(const Buffer &rhs)ipe::Buffer
operator[](int index)ipe::Bufferinline
operator[](int index) const ipe::Bufferinline
size() const ipe::Bufferinline
~Buffer()ipe::Buffer

ipe-7.1.4/build/doc/classipe_1_1_vector.html0000644000175000017500000007217112120621776020545 0ustar otfriedotfried Ipelib: ipe::Vector Class Reference

#include <ipegeo.h>

Public Member Functions

 Vector ()
 Vector (Angle alpha)
 Vector (double x0, double y0)
double sqLen () const
double len () const
Angle angle () const
Vector normalized () const
Vector orthogonal () const
double factorize (Vector &unit) const
bool snap (const Vector &mouse, Vector &pos, double &bound) const
bool operator== (const Vector &rhs) const
bool operator!= (const Vector &rhs) const
void operator+= (const Vector &rhs)
void operator-= (const Vector &rhs)
void operator*= (double rhs)
Vector operator+ (const Vector &rhs) const
Vector operator- (const Vector &rhs) const
Vector operator* (double rhs) const
Vector operator- () const

Public Attributes

double x
double y

Static Public Attributes

static Vector ZERO = Vector(0.0, 0.0)

Related Functions

(Note that these are not member functions.)

Streamoperator<< (Stream &stream, const Vector &rhs)
Vector operator* (double lhs, const Vector &rhs)
double dot (const Vector &lhs, const Vector &rhs)

Detailed Description

Two-dimensional vector.

Unlike some other libraries, I don't make a difference between points and vectors.

Constructor & Destructor Documentation

ipe::Vector::Vector ( )
inline

Uninitialized vector.

Vector::Vector ( Angle  alpha)
explicit

Construct a unit vector with this direction.

ipe::Vector::Vector ( double  x0,
double  y0 
)
inlineexplicit

Construct a vector.

Member Function Documentation

double ipe::Vector::sqLen ( ) const
inline

Return square of Euclidean length.

Return square of vector's length.

double Vector::len ( ) const
Angle Vector::angle ( ) const

Return angle of the vector (with positive x-direction).

The returned angle lies between -pi and +pi. Returns zero for the zero vector.

Vector Vector::normalized ( ) const

Return this vector normalized (with length one).

Normalizing the zero vector returns the vector (1,0).

Vector Vector::orthogonal ( ) const

Return this vector turned 90 degrees to the left.

double Vector::factorize ( Vector unit) const

Normalizes this vector into unit and returns length. If this is the zero vector, unit is set to (1,0).

bool Vector::snap ( const Vector mouse,
Vector pos,
double &  bound 
) const

Snap to nearby vertex.

If distance between mouse and this vector is less than bound, set pos to this vector and bound to the distance, and return true.

bool ipe::Vector::operator== ( const Vector rhs) const
inline

Equality.

bool ipe::Vector::operator!= ( const Vector rhs) const
inline

Inequality.

void ipe::Vector::operator+= ( const Vector rhs)
inline

Vector-addition.

void ipe::Vector::operator-= ( const Vector rhs)
inline

Vector-subtraction.

void ipe::Vector::operator*= ( double  rhs)
inline

Multiply vector by scalar.

Vector ipe::Vector::operator+ ( const Vector rhs) const
inline

Vector-addition.

Vector ipe::Vector::operator- ( const Vector rhs) const
inline

Vector-subtraction.

Vector ipe::Vector::operator* ( double  rhs) const
inline

Vector * scalar.

Vector ipe::Vector::operator- ( ) const
inline

Unary minus for Vector.

Friends And Related Function Documentation

Stream & operator<< ( Stream stream,
const Vector rhs 
)
related
Vector operator* ( double  lhs,
const Vector rhs 
)
related

Scalar * vector.

double dot ( const Vector lhs,
const Vector rhs 
)
related

Dotproduct of two vectors.

Member Data Documentation

Vector Vector::ZERO = Vector(0.0, 0.0)
static

The origin (zero vector).

double ipe::Vector::x

Coordinates are public.

double ipe::Vector::y

Coordinates are public.


The documentation for this class was generated from the following files:
  • ipegeo.h
  • ipegeo.cpp

ipe-7.1.4/build/doc/manual_29.html0000644000175000017500000001157112120621776016504 0ustar otfriedotfried Ipe Manual -- 7.1 Presentation stylesheets
7.2 Views7 Presentations7.1 Presentation stylesheets

7.1 Presentation stylesheets

A presentation must use a dedicated stylesheet. Presentations must use much larger fonts than what is normal for a figure. Don't try to make use of the "LARGE" and "huge" textsizes, but use a stylesheet that properly defines "normal" to be a large textsize.

Ipe comes with a style sheet presentation.isy that can be used for presentations. To create a new presentation, you can simply say:

 
  ipe -sheet presentation
Note that presentation.isy is meant to be used instead of basic.isy (not in addition to it).

This presentation stylesheet enlarges all standard sizes by a factor 2.8. Note the use of the <textstretch> element to magnify text:

<textstretch name="normal" value="2.8"/>
<textstretch name="large" value="2.8"/>
The text size you choose from the Ipe user interface ("large", for instance) is in fact used for two symbolic attributes, namely textsize (where large maps to \large) and textstretch (where it maps to no stretch in the standard style sheet). By setting the text stretch, you can magnify fonts.

In addition, the <layout> element in this stylesheet redefines the paper size to be of the correct proportions for a projector, and defines a smaller area of the paper as the frame. The frame is the area that should be used for the contents. The Insert text box function, for instance, creates text objects that fill exactly the width of the frame.

The <titlestyle> element defines the style of the page title outside the frame. You can set the title for each page using the Edit title & sections function in the Page menu.

The LaTeX-preamble defined in the <preamble> element redefines the standard font shape to cmss (Computer Modern Sans Serif). Many people find sans-serif fonts easier to read on a screen. In addition, it redefines the list environments to use less spacing, and the text styles to not justify paragraphs (the <textstyle> elements).

If you wish to use the page transition effects of Acrobat Reader, you can define the effects in the stylesheet (using <effect> elements), and set them using Edit effect in the View menu.

ipe-7.1.4/build/doc/classipe_1_1_string.html0000644000175000017500000007101712120621776020547 0ustar otfriedotfried Ipelib: ipe::String Class Reference

#include <ipebase.h>

Classes

struct  Imp

Public Member Functions

 String ()
 String (const char *str)
 String (const String &rhs)
 String (const String &rhs, int index, int len)
Stringoperator= (const String &rhs)
 ~String ()
char operator[] (int i) const
bool empty () const
bool isEmpty () const
const char * data () const
int size () const
void operator+= (const String &rhs)
void operator+= (char ch)
String substr (int i, int len=-1) const
String left (int i) const
String right (int i) const
bool operator!= (const String &rhs) const
int find (char ch) const
int rfind (char ch) const
int find (const char *rhs) const
void erase ()
void append (const String &rhs)
void append (char ch)
bool operator== (const String &rhs) const
bool operator< (const String &rhs) const
String operator+ (const String &rhs) const
int unicode (int &index) const
const char * z () const

Detailed Description

Strings and buffers.

String is is an implicitly shared byte string. It is designed to be efficient for strings of arbitrary length, and supposed to be passed by value (the size of String is a single pointer). Sharing is implicit—the string creates its own representation as soon as it is modified.

String can be used for binary data. For text, it is usually assumed that the string is UTF-8 encoded, but only the unicode member function actually requires this. In particular, all indices into the string are byte indices, not Unicode character indices.

Constructor & Destructor Documentation

String::String ( )

Construct an empty string.

String::String ( const char *  str)

Construct a string by making copy of str.

String::String ( const String rhs)

Copy constructor. This only copies the reference and takes constant time.

String::String ( const String rhs,
int  index,
int  len 
)

Construct a substring.

index must be >= 0. len can be negative or too large to return entire string.

String::~String ( )

Destruct string if reference count has reached zero.

Member Function Documentation

String & String::operator= ( const String rhs)

Assignment takes constant time.

char ipe::String::operator[] ( int  i) const
inline

Return character at index i.

bool ipe::String::empty ( ) const
inline

Is the string empty?

bool ipe::String::isEmpty ( ) const
inline

Is the string empty?

const char* ipe::String::data ( ) const
inline

Return read-only pointer to the data.

int ipe::String::size ( ) const
inline

Return number of bytes in the string.

void ipe::String::operator+= ( const String rhs)
inline

Operator syntax for append.

void ipe::String::operator+= ( char  ch)
inline

Operator syntax for append.

String ipe::String::substr ( int  i,
int  len = -1 
) const
inline

Create substring.

String ipe::String::left ( int  i) const
inline

Create substring at the left.

String String::right ( int  i) const

Create substring at the right.

Returns the entire string if i is larger than its length.

bool ipe::String::operator!= ( const String rhs) const
inline

Operator !=.

int String::find ( char  ch) const

Return index of first occurrence of ch.

Return -1 if character does not appear.

int String::rfind ( char  ch) const

Return index of last occurrence of ch.

Return -1 if character does not appear.

int String::find ( const char *  rhs) const

Return index of first occurrence of rhs.

Return -1 if not substring is not present.

void String::erase ( )

Make string empty.

void String::append ( const String rhs)

Append rhs to this string.

void String::append ( char  ch)

Append ch to this string.

bool String::operator== ( const String rhs) const

Equality operator (bytewise comparison).

bool String::operator< ( const String rhs) const

Inequality operator (bytewise comparison).

String String::operator+ ( const String rhs) const

Concatenate this string with rhs.

int String::unicode ( int &  index) const

Return Unicode value from UTF-8 string.

The index is incremented to the next UTF-8 character. This returns 0xfffd if there is any problem in parsing UTF-8.

const char * String::z ( ) const

Return a C style string with final zero byte.


The documentation for this class was generated from the following files:
  • ipebase.h
  • ipebase.cpp

ipe-7.1.4/build/doc/luaipe.html0000644000175000017500000001027312120621776016172 0ustar otfriedotfried Ipelib: Lua bindings for Ipe
Lua bindings for Ipe

These are the Lua methods provided by the Ipe program itself. They are only available to Lua code running inside Ipe.

Application user interface

The application user interface object provides the GUI for the Ipe program.

-- model is a Lua table containing methods that will be called 
-- by the ui when events occur
ui = AppUi(model)

id = ui:win()      -- returns window id of window
-- (to be used as parent for dialogs)
ui:close()         -- close window

ui:setActionState(name, t) -- set whether action is checked 
t = ui:actionState(name)   -- is action checked?

ui:explain(text)     -- show message in status bar for a few seconds
ui:setWindowTitle(caption)

ui:showNotes(n)

-- make a tool visible or invisible
-- tool is one of "layers", "properties", "bookmarks", "notes"
-- t is true or false
ui:showTool(tool, t)

-- set contents of attribute selectors from style sheet
ui:setupSymbolicNames(styleSheet)

-- set attribute values displayed in user interface
-- 'attributes' table see below
ui:setAttributes(styleSheet, attributes)

-- set layer list from page
ui:setLayers(page, view)  

ui:setActionState(action_name, true_or_false)
state = ui:actionState(action_name)

-- select one page and return page number (or nil if canceled)
pno = ui:selectPage(doc) 
-- select one view and return view number (or nil if canceled)
vno = ui:selectPage(doc, page_no)

The following methods work on the canvas inside the UI:

ui:setPage(page, pgno, view, styleSheet) -- set page shown on canvas
ui:setSnap(snap)                    -- for 'snap' table see below
ui:setFontPool(p)       -- an opaque object obtained from an ipe.Document

-- 'pan' is a vector indicating the user coordinates at canvas center
v = ui:pan()       
ui:setPan(v)

zoom = ui:zoom()        -- a number
ui:setZoom(zoom)

v = ui:pos()            -- current mouse position, after snapping
v = ui:unsnappedPos()   -- current mouse position, before snapping
v = ui:simpleSnapPos()  -- same, but ignoring angular snap
v = ui:globalPos()      -- mouse position on screen

v = ui:canvasSize()     -- size of canvas in pixels

ui:setNumbering(t)      -- true or false
ui:setFifiVisible(t)    -- true or false
ui:setSelectionVisible(t) -- true or false

ui:update()             -- update canvas and tool
ui:update(false)        -- update tool only
ui:finishTool()

ui:panTool()
ui:selectTool()
ui:transformTool()
ui:shapeTool()

ipe-7.1.4/build/doc/classipe_1_1_xml_parser.html0000644000175000017500000004234412120621776021416 0ustar otfriedotfried Ipelib: ipe::XmlParser Class Reference

#include <ipexml.h>

Inherited by FontmapParser, and ipe::ImlParser.

Public Member Functions

 XmlParser (DataSource &source)
virtual ~XmlParser ()
int parsePosition () const
String parseToTag ()
bool parseAttributes (XmlAttributes &attr, bool qm=false)
bool parsePCDATA (String tag, String &pcdata)
bool isTagChar (int ch)
void getChar ()
bool eos ()
void skipWhitespace ()

Protected Member Functions

String parseToTagX ()

Protected Attributes

DataSourceiSource
String iTopElement
int iCh
int iPos

Detailed Description

Base class for XML stream parsing.

This is the base class for Ipe's XML parser. It only provides some utility functions for parsing tags and PCDATA. Derived classes implement the actual parsing using recursive descent parsers—after experimenting with various schemes for XML parsing, this seems to work best for Ipe.

Tag names and attribute names must consist of ASCII letters only. Only entities for '&', '<', and '>' are recognized.

Constructor & Destructor Documentation

XmlParser::XmlParser ( DataSource source)

Construct with a data source.

XmlParser::~XmlParser ( )
virtual

Virtual destructor, so one can destroy through pointer.

Member Function Documentation

int ipe::XmlParser::parsePosition ( ) const
inline
String XmlParser::parseToTag ( )

Parse whitespace and the name of a tag.

Like ParseToTagX, but silently skips over all tags whose name starts with "x-"

bool XmlParser::parseAttributes ( XmlAttributes attr,
bool  qm = false 
)

Parse XML attributes.

Returns with stream just after >. Caller can check whether the tag ended with a / by checking attr.slash().

Set qm to true to allow a question mark just before the >.

bool XmlParser::parsePCDATA ( String  tag,
String pcdata 
)

Parse PCDATA.

Checks whether the data is terminated by </tag>, and returns with stream past the >.

bool ipe::XmlParser::isTagChar ( int  ch)
inline
void ipe::XmlParser::getChar ( )
inline
bool ipe::XmlParser::eos ( )
inline
void XmlParser::skipWhitespace ( )
String XmlParser::parseToTagX ( )
protected

Parse whitespace and the name of a tag.

If the tag is a closing tag, skips > and returns with stream after that. Otherwise, returns with stream just after the tag name.

Comments and <!TAG .. > are skipped silently.

Member Data Documentation

DataSource& ipe::XmlParser::iSource
protected
String ipe::XmlParser::iTopElement
protected
int ipe::XmlParser::iCh
protected
int ipe::XmlParser::iPos
protected

The documentation for this class was generated from the following files:
  • ipexml.h
  • ipexml.cpp

ipe-7.1.4/build/doc/manual_21.html0000644000175000017500000000726412120621776016500 0ustar otfriedotfried Ipe Manual -- 5 Snapping
6 StylesheetsTop4 Object types5 Snapping

5 Snapping

One of the nice features of Ipe is the possibility of having the mouse snap to other objects during entry or moving. Certain features on the canvas become "magnetic", and it is very easy to align objects to each other, to place new objects properly with respect to the present objects and so on.

Snapping comes in three flavors: grid snapping, context snapping, and angular snapping.

In general, you turn a snapping mode on by pressing one of the buttons in the Snap toolbar, or selecting the equivalent functions in the Snap menu. The buttons are independent, you can turn them on and off independently. (The snapping modes, however, are not independent. See below for the precise interaction.) The keyboard shortcuts are rather convenient since you will want to toggle snapping modes on and off while in the middle of creating or editing some object.

Whenever one of the snapping modes is enabled, you will see a little cross near the cursor position. This is the secondary cursor Fifi.3 Fifi marks the position the mouse is snapped to.

ipe-7.1.4/build/doc/bc_s.png0000644000175000017500000000125012120621776015434 0ustar otfriedotfried‰PNG  IHDR /ð9ÐoIDATxíMLAÇßìN»»¥ívKùPJik±R5^ŒChÂŃ!Dzƒ *U4VƒbÄD1~`8xà@ˆ^¿?ð𤡸Ý@јÝná`JLLÝØ¦ƒÜXi v«9ê)·}aV±&Ò0)›¼ð(‰zÛküNcFPÛù'@é¨KZK%!13§5£}Ý€ÒdÀã°’>´Åç´çhï¹G…ÉZ ïz×Ú—Éi£“ì–º=…@O¹«È‚1Ó¯¦3ãF«[ºä’d²¾JÒã`|^3˜Ý\›¿¡]²ó•'fçÓùyˆÄîçâÙ@¥Cos˧d:?$lhûnÝ× nm\†$cÔL6Ñý »Ì´x@N¦oPÀ®Î‘òÕ”€GÔ÷>9¹¨Q@ã±á“.‡qŠÜ´¼°Ø ”PCt(á«yŒQ$±°hÔNý8¤¥Ë MNjÿ$þßþŲo_ƒsLIEND®B`‚ipe-7.1.4/build/doc/manual_18.html0000644000175000017500000000711012120621776016474 0ustar otfriedotfried Ipe Manual -- 4.3 Image objects
4.4 Group objects4 Object types4.2 Text objects4.3 Image objects

4.3 Image objects

Images are inserted using the Insert image ipelet (in the Ipelets menu). Once in a drawing, you can scale, stretch, and rotate an image. You can read in some scanned drawing and draw on top of it within Ipe. This is useful if you have a drawing on paper and want to make an Ipe version of it.

There are three functions for inserting images: one for images in general, one for JPEG images, and one for pasting from the clipboard.

If your image is in a lossless bitmap format such as PNG, GIF, or BMP, then the first function is appropriate. If your image is in JPEG (JPG) format, then the second function is the right one (it results in much smaller files, as the image is then stored internally in JPEG format, instead of a bitmap). You can also paste an image that is on the clipboard (this should not be used for JPEG images, as you would then store the bitmap). One has to be a bit careful with this, as Insert bitmap does accept JPG files.

Images are stored efficiently in PDF format. It is reasonable to create PDF presentations with lots of JPEG photographs in Ipe. Saving in Postscript is not efficient, as Ipe generates clean 7-bit Postscript files. Also, multiple copies of the same image are embedded only once in PDF documents, but are embedded once for each occurrence in Postscript output.

ipe-7.1.4/build/doc/classipe_1_1_bitmap-members.html0000644000175000017500000002774312120621776022154 0ustar otfriedotfried Ipelib: Member List
ipe::Bitmap Member List

This is the complete list of members for ipe::Bitmap, including all inherited members.

Bitmap()ipe::Bitmap
Bitmap(int width, int height, TColorSpace colorSpace, int bitsPerComponent, Buffer data, TFilter filter, bool deflate=false)ipe::Bitmap
Bitmap(const XmlAttributes &attr, String data)ipe::Bitmap
Bitmap(const XmlAttributes &attr, Buffer data)ipe::Bitmap
Bitmap(const Bitmap &rhs)ipe::Bitmap
bitsPerComponent() const ipe::Bitmapinline
colorKey() const ipe::Bitmap
colorSpace() const ipe::Bitmapinline
components() const ipe::Bitmapinline
data() const ipe::Bitmapinline
EDCTDecode enum valueipe::Bitmap
EDeviceCMYK enum valueipe::Bitmap
EDeviceGray enum valueipe::Bitmap
EDeviceRGB enum valueipe::Bitmap
EDirect enum valueipe::Bitmap
EFlateDecode enum valueipe::Bitmap
equal(Bitmap rhs) const ipe::Bitmap
filter() const ipe::Bitmapinline
height() const ipe::Bitmapinline
isNull() const ipe::Bitmapinline
objNum() const ipe::Bitmapinline
operator!=(const Bitmap &rhs) const ipe::Bitmapinline
operator<(const Bitmap &rhs) const ipe::Bitmapinline
operator=(const Bitmap &rhs)ipe::Bitmap
operator==(const Bitmap &rhs) const ipe::Bitmapinline
pixelData() const ipe::Bitmap
renderData() const ipe::Bitmapinline
saveAsXml(Stream &stream, int id, int pdfObjNum=-1) const ipe::Bitmap
setColorKey(int key)ipe::Bitmap
setObjNum(int objNum) const ipe::Bitmapinline
setRenderData(MRenderData *data) const ipe::Bitmap
size() const ipe::Bitmapinline
TColorSpace enum nameipe::Bitmap
TFilter enum nameipe::Bitmap
width() const ipe::Bitmapinline
~Bitmap()ipe::Bitmap

ipe-7.1.4/build/doc/example2.svg0000644000175000017500000003040412120621776016261 0ustar otfriedotfried ipe-7.1.4/build/doc/classipe_1_1_line-members.html0000644000175000017500000001152412120621776021615 0ustar otfriedotfried Ipelib: Member List
ipe::Line Member List

This is the complete list of members for ipe::Line, including all inherited members.

dir() const ipe::Lineinline
distance(const Vector &v) const ipe::Line
intersects(const Line &line, Vector &pt)ipe::Line
iPipe::Line
Line()ipe::Lineinlineexplicit
Line(const Vector &p, const Vector &dir)ipe::Lineexplicit
normal() const ipe::Lineinline
project(const Vector &v) const ipe::Line
side(const Vector &p) const ipe::Line
through(const Vector &p, const Vector &q)ipe::Linestatic

ipe-7.1.4/build/doc/manual_13.html0000644000175000017500000000747012120621776016500 0ustar otfriedotfried Ipe Manual -- 3.10 Layers
3.11 Mouse shortcuts3 General Concepts3.9 Groups3.10 Layers

3.10 Layers

A page of an Ipe document consists of one or more layers. Each object on the page belongs to a layer. There is no relationship between layers and the back-to-front ordering of objects, so the layer is really just an attribute of the object.

The layers of the current page are displayed in the layer list, at the bottom left of the Ipe window. The checkmark to the left of the layer name determines whether the layer is visible. The layer marked with a yellow background is the active layer. New objects are always created in the active layer. You can change the active layer by left-clicking on the layer name.

By right-clicking on a layer name, you open the layer context menu that allows you to change layer attributes, to rename layers, to delete empty layers, and to change the ordering of layers in the layer list (this ordering has no other significance).

A layer may be editable or locked. Objects can be selected and modified only if their layer is editable. Locked layer are displayed in the layer list with a pink background. You can lock and unlock layers from the layer context menu, but note that the active layer cannot be locked.

A layer may have snapping on or off—objects will behave magnetically only if their layer has snapping on. Layers without snapping are displayed dimmed in the layer list.

Layers are also used to create pages that are displayed incrementally in Acrobat Reader. Once you have distributed your objects over various layers, you can create views, which defines in what order which layers of the page are shown.

ipe-7.1.4/build/doc/manual_12.html0000644000175000017500000000563112120621776016474 0ustar otfriedotfried Ipe Manual -- 3.9 Groups
3.10 Layers3 General Concepts3.8 Zoom and pan3.9 Groups

3.9 Groups

It is often convenient to treat a collection of objects as a single object. This can be achieved by grouping objects. The result is a geometric object, which can be moved, scaled, rotated etc. as a whole. To edit its parts or to move parts of it with respect to others, however, you have to un-group the object, which decomposes it into its component objects. To un-group a group object, select it, bring up the object menu, and select the Ungroup function.

Group objects can be elements of other groups, so you can create a hierarchy of objects.

You can also add a clipping path to a group, which will restrict the drawing of the group to the area inside the clipping path.

ipe-7.1.4/build/doc/lingrad1.svg0000644000175000017500000000247512120621776016254 0ustar otfriedotfried ipe-7.1.4/build/doc/classipe_1_1_platform-members.html0000644000175000017500000001241112120621776022506 0ustar otfriedotfried Ipelib: Member List
ipe::Platform Member List

This is the complete list of members for ipe::Platform, including all inherited members.

currentDirectory()ipe::Platformstatic
DebugHandler typedefipe::Platform
fileExists(String fname)ipe::Platformstatic
fontmapFile()ipe::Platformstatic
initLib(int version)ipe::Platformstatic
latexDirectory()ipe::Platformstatic
libVersion()ipe::Platformstatic
pathSeparator()ipe::Platformstatic
readFile(String fname)ipe::Platformstatic
runPdfLatex(String dir)ipe::Platformstatic
setDebug(bool debug)ipe::Platformstatic

ipe-7.1.4/build/doc/classipe_1_1_pdf_null-members.html0000644000175000017500000001300112120621776022461 0ustar otfriedotfried Ipelib: Member List
ipe::PdfNull Member List

This is the complete list of members for ipe::PdfNull, including all inherited members.

array() const ipe::PdfObjvirtual
boolean() const ipe::PdfObjvirtual
dict() const ipe::PdfObjvirtual
name() const ipe::PdfObjvirtual
null() const ipe::PdfNullvirtual
number() const ipe::PdfObjvirtual
PdfNull()ipe::PdfNullinlineexplicit
ref() const ipe::PdfObjvirtual
repr() const ipe::PdfObj
string() const ipe::PdfObjvirtual
write(Stream &stream) const ipe::PdfNullvirtual
~PdfObj()=0ipe::PdfObjpure virtual

ipe-7.1.4/build/doc/namespacemembers_func.html0000644000175000017500000000524412120621776021237 0ustar otfriedotfried Ipelib: Namespace Members
 

ipe-7.1.4/build/doc/classipe_1_1_sub_path-members.html0000644000175000017500000001574512120621776022504 0ustar otfriedotfried Ipelib: Member List
ipe::SubPath Member List

This is the complete list of members for ipe::SubPath, including all inherited members.

addToBBox(Rect &box, const Matrix &m, bool cp) const =0ipe::SubPathpure virtual
asClosedSpline() const ipe::SubPathvirtual
asCurve() const ipe::SubPathvirtual
asEllipse() const ipe::SubPathvirtual
closed() const ipe::SubPathvirtual
distance(const Vector &v, const Matrix &m, double bound) const =0ipe::SubPathpure virtual
draw(Painter &painter) const =0ipe::SubPathpure virtual
EClosedSpline enum valueipe::SubPath
ECurve enum valueipe::SubPath
EEllipse enum valueipe::SubPath
save(Stream &stream) const =0ipe::SubPathpure virtual
snapBnd(const Vector &mouse, const Matrix &m, Vector &pos, double &bound) const =0ipe::SubPathpure virtual
snapVtx(const Vector &mouse, const Matrix &m, Vector &pos, double &bound) const =0ipe::SubPathpure virtual
type() const =0ipe::SubPathpure virtual
Type enum nameipe::SubPath
~SubPath()=0ipe::SubPathpure virtual

ipe-7.1.4/build/doc/manual_47.html0000644000175000017500000001642512120621776016507 0ustar otfriedotfried Ipe Manual -- 11 Using Ipe figures in Latex
12 Command line options and environment variablesTop10 If you have used Ipe 6 before11 Using Ipe figures in Latex

11 Using Ipe figures in Latex

Most Latex installations support the inclusion of figures in Encapsulated Postscript (EPS) format (the "Encapsulated" means that there is only a single Postscript page and that it contains a bounding box of the figure).

The standard way of including EPS figures is using the graphicx package. If you are not familiar with it, here is a quick overview. In the preamble of your document, add the declaration:

  \usepackage{graphicx}
One useful attribute to this declaration is draft, which stops LaTeX from actually including the figures—instead, a rectangle with the figure filename is shown:
  \usepackage[draft]{graphicx}

To include the figure "figure1.eps", you use the command:

  \includegraphics{figs/figure1}
Note that it is common not to specify the file extension ".eps". The command \includegraphics has various options to scale and rotate the figure. For instance, to scale the same figure to 50%, use:
  \includegraphics[scale=0.5]{figs/figure1}
To scale such that the width of the figure becomes 5 cm:
  \includegraphics[width=5cm]{figs/figure1}
Instead, one can specify the required height with height.

Here is an example that scales a figure to 200% and rotates it by 45 degrees counter-clockwise. Note that the scale argument should be given before the angle argument.

  \includegraphics[scale=2,angle=45]{figs/figure1}

Let's stress once again that these commands are the standard commands for including EPS files in a LaTeX document. Ipe files neither require nor support any special treatment. If you are used to other commands for EPS inclusion, such as the old-fashioned epsfig package,4 you can use them as well for Ipe figures. If you want to know more about the LaTeX packages for including graphics and producing colour, check the grfguide.tex document that is probably somewhere in your TeX installation.


If you are a user of Pdflatex (a version of Latex that produces PDF instead of DVI output), you cannot include EPS files. Instead, save your Ipe figures in PDF format, and include them in the way described above.

There is a slight complication here: Each page of a PDF document can carry several "bounding boxes", such as the MediaBox (which indicates the paper size), the CropBox (which indicates how the paper will by cut), or the ArtBox (which indicates the extent of the actual contents of the page). Ipe automatically saves, for each page, the paper size in the MediaBox, and a bounding box for the drawing in the ArtBox. Ipe also puts the bounding box in the CropBox unless this has been turned off by the stylesheet.

Now, when including a PDF figure, Pdflatex will (by default) first look at the CropBox, and, if that is not set, fall back on the MediaBox. It does not inspect the ArtBox, and so it is important that you use the correct stylesheet for the kind of figure you are making—with cropping for figures to be included, without cropping for presentations (as otherwise Acrobat Reader will not display full pages—Acrobat Reader actually crops each page to the CropBox).

If you have a recent version of Pdflatex (1.40 or higher), you can actually ask Pdflatex to inspect the ArtBox by saying \pdfpagebox5 in your Latex file's preamble.

You can save all your figures in both EPS and PDF format, so that you can run both Latex and Pdflatex on your document—when including figures, Latex will look for the EPS variant, while Pdflatex will look for the PDF variant. (Here it comes in handy that you didn't specify the file extension in the \includegraphics command.)

It would be cumbersome to have to save an Ipe figure in both formats each time you modify it. What you should do instead, is to always save in one format—let's say EPS. You can then write a shell script or batch file that calls ipetoipe to do the conversion to PDF. Alternatively, you can enable auto-exporting from EPS to PDF in Ipe.


On the other hand, if you only use Pdflatex, you might opt to exploit a feature of Pdflatex: You can keep all the figures for a document in a single, multi-page Ipe document, with one figure per page. You can then include the figures one by one into your document by using the page argument of \includegraphics.

For example, to include page 3 from the PDF file "figures.pdf" containing several figures, you could use

  \includegraphics[page=3]{figures}
ipe-7.1.4/build/doc/classipe_1_1_stream.html0000644000175000017500000004177012120621776020537 0ustar otfriedotfried Ipelib: ipe::Stream Class Reference

#include <ipebase.h>

Inherited by ipe::A85Stream, ipe::Base64Stream, ipe::DeflateStream, ipe::TellStream, and PercentStream.

Public Member Functions

virtual ~Stream ()
virtual void putChar (char ch)=0
virtual void close ()
virtual void putString (String s)
virtual void putCString (const char *s)
virtual void putRaw (const char *data, int size)
Streamoperator<< (char ch)
Streamoperator<< (const String &s)
Streamoperator<< (const char *s)
Streamoperator<< (int i)
Streamoperator<< (double d)
void putHexByte (char b)
void putXmlString (String s)

Detailed Description

Abstract base class for output streams.

Constructor & Destructor Documentation

Stream::~Stream ( )
virtual

Virtual destructor.

Member Function Documentation

virtual void ipe::Stream::putChar ( char  ch)
pure virtual
void Stream::close ( )
virtual

Close the stream. No more writing allowed!

Reimplemented in ipe::DeflateStream, ipe::Base64Stream, and ipe::A85Stream.

void Stream::putString ( String  s)
virtual

Output string.

Default implementation uses PutChar.

Reimplemented in ipe::FileStream, and ipe::StringStream.

void Stream::putCString ( const char *  s)
virtual

Output C string.

Default implementation uses PutChar.

Reimplemented in ipe::FileStream, and ipe::StringStream.

void Stream::putRaw ( const char *  data,
int  size 
)
virtual

Output raw character data.

Default implementation uses PutChar.

Reimplemented in ipe::FileStream, and ipe::StringStream.

Stream& ipe::Stream::operator<< ( char  ch)
inline

Output character.

Stream& ipe::Stream::operator<< ( const String s)
inline

Output string.

Stream& ipe::Stream::operator<< ( const char *  s)
inline

Output C string.

Stream & Stream::operator<< ( int  i)

Output integer.

Stream & Stream::operator<< ( double  d)

Output double.

void Stream::putHexByte ( char  b)

Output byte in hexadecimal.

void Stream::putXmlString ( String  s)

Save a string with XML escaping of &, >, <, ", '.


The documentation for this class was generated from the following files:
  • ipebase.h
  • ipebase.cpp

ipe-7.1.4/build/doc/classipe_1_1_canvas_observer.html0000644000175000017500000001607512120621776022426 0ustar otfriedotfried Ipelib: ipe::CanvasObserver Class Reference
ipe::CanvasObserver Class Reference

#include <ipecanvas.h>

Public Member Functions

virtual void canvasObserverWheelMoved (int degrees)
virtual void canvasObserverMouseAction (int button)
virtual void canvasObserverPositionChanged ()
virtual void canvasObserverToolChanged (bool hasTool)
virtual void canvasObserverSizeChanged ()

Member Function Documentation

void CanvasObserver::canvasObserverWheelMoved ( int  degrees)
virtual
void CanvasObserver::canvasObserverMouseAction ( int  button)
virtual
void CanvasObserver::canvasObserverPositionChanged ( )
virtual
void CanvasObserver::canvasObserverToolChanged ( bool  hasTool)
virtual
void CanvasObserver::canvasObserverSizeChanged ( )
virtual

The documentation for this class was generated from the following files:
  • ipecanvas.h
  • ipecanvas.cpp

ipe-7.1.4/build/doc/example5.svg0000644000175000017500000002207112120621776016265 0ustar otfriedotfried ipe-7.1.4/build/doc/classipe_1_1_file_source.html0000644000175000017500000001226012120621776021533 0ustar otfriedotfried Ipelib: ipe::FileSource Class Reference
ipe::FileSource Class Reference

#include <ipebase.h>

Inherits ipe::DataSource.

Public Member Functions

 FileSource (std::FILE *file)
virtual int getChar ()
- Public Member Functions inherited from ipe::DataSource
virtual ~DataSource ()=0

Detailed Description

Data source for parsing from a file.

Constructor & Destructor Documentation

FileSource::FileSource ( std::FILE *  file)

Member Function Documentation

int FileSource::getChar ( )
virtual

Get one more character, or EOF.

Implements ipe::DataSource.


The documentation for this class was generated from the following files:
  • ipebase.h
  • ipebase.cpp

ipe-7.1.4/build/doc/nav_f.png0000644000175000017500000000023112120621776015615 0ustar otfriedotfried‰PNG  IHDR8³»`IDATxíÝK€ EÑ–·[†øBÑmkâÄÂH—prÓ¼.‚Žó‚ꎤR6Z VI±E‚5j³„lóš›iI˜¬ÞêçJ0ŒÑÑ/Žû›™uøñóÞ¿6sH ÝõyIEND®B`‚ipe-7.1.4/build/doc/example6.svg0000644000175000017500000001174112120621776016270 0ustar otfriedotfried ipe-7.1.4/build/doc/manual_51.html0000644000175000017500000002635712120621776016507 0ustar otfriedotfried Ipe Manual -- 13 History and acknowledgments
14 CopyrightTop12 Command line options and environment variables13 History and acknowledgments

13 History and acknowledgments

The name "Ipe" is older than the program itself. When I made figures for my papers using Idraw in 1992, I was annoyed that I had to store two versions of each figure: one with Latex text, one with Postscript information. I came up with a file format that I called "Ipe", for "Integrated Picture Environment", and which was at the same time legal Latex source code and a legal Postscript file.

When I wrote the first version of Ipe at Utrecht University in the summer of 1993, it created this file format directly, and inherited the name. The first versions of Ipe (Ipe 2.0 up to 4.1) were based on my experiences with Idraw, XFig, and Jean-Pierre Merlet's JPDraw, used IRIS-GL and Mark Overmars' FORMS library, and run on SGI workstations only.

Due to popular demand, I spent two weeks in the summer of 1994 to teach myself Motif and to rewrite Ipe to run under the X window system. Unfortunately, two weeks were really not enough, and the 1994 X-version of Ipe was somewhat of a hack. I didn't have time to port the code that displayed bitmaps on the screen, it crashed on both monochrome and truecolor (24-bit) displays, and was in general quite unmaintainable.

These versions of Ipe were supported by the Netherlands' Organization for Scientific Research (NWO), and I would never have started working on it without Geert-Jan Giezeman's PLAGEO library. For testing, support, and inspiration in that original period, I'm grateful to Mark de Berg, Maarten Pennings, Jules Vleugels, Vincenzo Ferrucci, and Anil Rao. Many students of the department at Utrecht University served as alpha-testers (who apparently referred to Ipe as "the cute little core-dumper").

I gave a presentation about Ipe at the Dagstuhl Workshop on Computational Geometry in 1995, and made a poster presentation at the ACM Symposium on Computational Geometry in Vancouver in the same year. Both served to create a small but faithful community of Ipe addicts within the Computational Geometry community.

Ipe proved itself invaluable to me over the years, especially when we used it to make all the illustrations in our book "Computational Geometry: Theory and Applications" (Springer 1997, with Mark de Berg, Marc van Kreveld, and Mark Overmars). Nevertheless, the problems were undeniable: It was hard to compile Ipe on other C++ compilers and it only worked on 8-bit displays. It was only due to the efforts of Ipe fans such as Tycho Strijk, Robert-Paul Berretty, Alexander Wolff, and Sariel Har-Peled that the 1994 version of Ipe continued to be used until 2003.

I was teaching myself C++ while writing the first version of Ipe, and it showed—Ipe 5 was full of elementary object-oriented design mistakes. When teaching C++ to second-year students at Postech in 1996 I started to think about a clean rewrite of Ipe. My first notes on such a rewrite stem from evenings spent at a hotel in Machida, close to IBM Tokyo in July 1996 (the idea at that time was to embed Ipe into Emacs!). It proved impossible, though, to do a full rewrite next to teaching and research, and nothing really happened until the Dagstuhl Workshop on Computational Geometry in 2001, where Christian Knauer explained to me how to use Pdflatex to create presentations. I realized that PDF was ideally suited for a new version of Ipe.

Ipe 5 figures were at the same time Latex and Postscript files, and required special handling to be included into Latex documents, which sometimes required a bit of explaining when talking to co-authors or publishers. While editing a figure, Ipe 5 kept a Ghostscript window open that would show what the figure looked like after processing by Latex.

Several developments that had happened between 1993 and 2001 allowed me to use a completely new approach: First, Hàn Thê Thàn's Pdflatex takes Latex source and directly produces a PDF file with a PDF representation of the text and all necessary fonts. Second, Derek Noonburg's Xpdf contained an open-source PDF parser that I could use to parse this PDF representation and to extract the processed text and fonts. Third, all relevant Latex fonts are now available as scalable Type1 fonts, and so it is possible to embed Latex text and formulas in figures that may still need to be scaled later. Finally, the Ghostscript window was no longer necessary as Ipe could use the beautiful Freetype library to directly display the text on-screen as it will appear on paper.

Directly after the Dagstuhl workshop I implemented a proof-of-concept: I defined the Ipe XML format (there was no question that Ipe 6 would have to be able to communicate in XML, of course), wrote "ipe5toxml" (reusing my old Ipe parsing code) and a program that runs Pdflatex, parses its PDF output, extracts text objects and font data, and creates a PDF file for the whole Ipe figure.

All that remained to be done was to rewrite the user interface. Mark de Berg and the TU Eindhoven made it possible for me to take some time off from teaching and research. The final design changes were made during the Second McGill-INRIA Workshop on Computational Geometry in Computer Graphics at McGill's Bellairs Research Institute in February 2003, and much inspiration was due to the atmosphere at the workshop and the magnificient cooking by Gwen, Bellair's chef. An early preview of Ipe 6.0 was "formally" released at the Dagstuhl Workshop on Computational Geometry in March 2003, to celebrate the Dagstuhl influence on Ipe.

Other than the file format, there weren't really that many changes to Ipe's functionality between Ipe 5 and Ipe 6. René van Oostrum insisted that no self-respecting drawing program can do without style sheets and layers. Views allow you to incrementally build up a page in a PDF presentation.

I also revised the interface to ipelets (which used to be called "Iums" in the good old days when people still thought that "applets" were small apples)—it is now based on dynamically loaded libraries (a technology that was still somewhat poorly understood in the early nineties, at least by me).

And, of course, there was a Windows version of Ipe 6. Who would have thought that ten years earlier!

There were many releases of Ipe 6.0, all of them called "previews", because I never considered that I had reached a stable state. A number of experimental features were tried and either built into Ipe or discarded. Ipe 6 migrated from Qt 2 and Qt 3 to Qt 4, a somewhat painful process due to a number of annyoing Qt bugs that cost me a lot of time.

When in 2007 I discovered the fantastic Cairo library for rendering, I immediately decided to switch Ipe to use this: a small dedicated library with a nice API to do the rendering, instead of the buggy monster that was Qt. The Cairo API fit Ipe so well that I could write a Cairo painter for Ipe in an hour or so. Cairo supports Freetype directly, instead of Ipe having to render each glyph into a bitmap that is then blit onto the canvas.

I made the huge mistake of announcing on the Ipe discussion list that Ipe 6.0 preview 28 was the last version of Ipe 6, and that there would soon be a new version, Ipe 7. I should have known that this was impossible during a time where I advised several graduate students, taught several new courses, and went through the tenure process. I had to release several bugfix releases of Ipe 6 while really wanting to work on Ipe 7.

However, the delay left me with enough time to carefully think about another change I wanted to make: It would be nice if Ipe embedded a scripting language that could be used to write simple ipelets without compilation. I looked at Scheme/Guile, Python, and Lua, and finally decided for Lua: a small, elegant, stable language with a tiny footprint, easily embedded with a very nice C interface.

In 2009, I had my first sabbatical ever, which I spent in the group of Ulrik Brandes at the University of Konstanz. Here I finally had the time to work on Ipe 7, and I'm very grateful to Ulrik and all members of his group for the wonderful time I had in Konstanz. Next to the two big changes mentioned above, Ipe 7 introduced tiling patterns, gradients, clipping paths, transparency, user-definable arrows and marks, and SVG output.

I wanted to avoid Qt in Ipe 7 as it had caused me quite a bit of pain during the life of Ipe 6, but it was hard to find a good replacement that would allow Ipe to run on Linux, Windows, and Macs. During the Korean Workshop on Computational Geometry organized by Tetsuo Asano at Hakusan seminar house in June 2009, I discussed using Ipe on tablet PCs with Vida Dujmovic, Jit Bose, and Stefan Langerman. It is their fault that Ipe 7 comes with a tablet input tool, and finally Stefan and Sébastien Collette convinced me that there isn't really an alternative to Qt that has the same support for tablets and Macs. So Ipe 7 is still using Qt, but in a much more restricted way than before, and hopefully much less sensitive to bugs in Qt.

ipe-7.1.4/build/doc/structipe_1_1_text_1_1_x_form.html0000644000175000017500000001415512120621776022456 0ustar otfriedotfried Ipelib: ipe::Text::XForm Struct Reference
ipe::Text::XForm Struct Reference

#include <ipetext.h>

Public Attributes

unsigned long int iRefCount
Buffer iStream
Rect iBBox
int iDepth
std::vector< int > iFonts
double iStretch

Member Data Documentation

unsigned long int ipe::Text::XForm::iRefCount
Buffer ipe::Text::XForm::iStream
Rect ipe::Text::XForm::iBBox
int ipe::Text::XForm::iDepth
std::vector<int> ipe::Text::XForm::iFonts
double ipe::Text::XForm::iStretch

The documentation for this struct was generated from the following file:
  • ipetext.h

ipe-7.1.4/build/doc/classipe_1_1_file_source-members.html0000644000175000017500000000603012120621776023161 0ustar otfriedotfried Ipelib: Member List
ipe::FileSource Member List

This is the complete list of members for ipe::FileSource, including all inherited members.

FileSource(std::FILE *file)ipe::FileSource
getChar()ipe::FileSourcevirtual
~DataSource()=0ipe::DataSourcepure virtual

ipe-7.1.4/build/doc/manual_ipe_copyright.html0000644000175000017500000000650012120621776021113 0ustar otfriedotfried Ipe Manual -- 14 Copyright
ContentsTop13 History and acknowledgments14 Copyright

14 Copyright

Ipe is "free," this means that everyone is free to use it and free to redistribute it on certain conditions. Ipe is not in the public domain; it is copyrighted and there are restrictions on its distribution as follows:

Copyright © 1993–2012 Otfried Cheong

This program is free software; you can redistribute it and/or modify it under the terms of the Gnu General Public License as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version.

As a special exception, you have permission to link Ipe with the CGAL library and distribute executables, as long as you follow the requirements of the Gnu General Public License in regard to all of the software in the executable aside from CGAL.

This program 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 General Public License for more details.

ipe-7.1.4/build/doc/classipe_1_1_matrix.html0000644000175000017500000006214712120621776020551 0ustar otfriedotfried Ipelib: ipe::Matrix Class Reference

#include <ipegeo.h>

Public Member Functions

 Matrix ()
 Matrix (const Linear &linear)
 Matrix (const Linear &linear, const Vector &t)
 Matrix (double m11, double m21, double m12, double m22, double t1, double t2)
 Matrix (const Vector &v)
 Matrix (String str)
Matrix inverse () const
Vector operator* (const Vector &rhs) const
Bezier operator* (const Bezier &rhs) const
Vector translation () const
Linear linear () const
bool isIdentity () const
bool operator== (const Matrix &rhs) const

Public Attributes

double a [6]

Related Functions

(Note that these are not member functions.)

Streamoperator<< (Stream &stream, const Matrix &rhs)
Bezier operator* (const Bezier &rhs) const
Vector operator* (const Vector &rhs) const
Matrix operator* (const Matrix &lhs, const Matrix &rhs)
Arc operator* (const Matrix &lhs, const Arc &rhs)

Detailed Description

Homogeneous transformation in the plane.

Constructor & Destructor Documentation

ipe::Matrix::Matrix ( )
inline

Create identity matrix.

ipe::Matrix::Matrix ( const Linear linear)
inline

Create linear matrix.

ipe::Matrix::Matrix ( const Linear linear,
const Vector t 
)
inlineexplicit
ipe::Matrix::Matrix ( double  m11,
double  m21,
double  m12,
double  m22,
double  t1,
double  t2 
)
inlineexplicit

Create matrix with given coefficients.

ipe::Matrix::Matrix ( const Vector v)
inlineexplicit

Create translation matrix.

Matrix::Matrix ( String  str)
explicit

Parse string.

Member Function Documentation

Matrix Matrix::inverse ( ) const

Return inverse.

Vector ipe::Matrix::operator* ( const Vector rhs) const
inline
Bezier ipe::Matrix::operator* ( const Bezier rhs) const
inline
Vector ipe::Matrix::translation ( ) const
inline

Return translation component.

Linear ipe::Matrix::linear ( ) const
inline

Return linear transformation component of this affine transformation.

bool ipe::Matrix::isIdentity ( ) const
inline

Is this the identity matrix?

bool ipe::Matrix::operator== ( const Matrix rhs) const
inline

Check for equality of two matrices.

Friends And Related Function Documentation

Stream & operator<< ( Stream stream,
const Matrix rhs 
)
related
Bezier operator* ( const Bezier rhs) const
related

Transform Bezier spline.

Vector operator* ( const Vector rhs) const
related

Matrix times vector.

Matrix operator* ( const Matrix lhs,
const Matrix rhs 
)
related

Matrix multiplication.

Arc operator* ( const Matrix lhs,
const Arc rhs 
)
related

Transform arc.

Member Data Documentation

double ipe::Matrix::a[6]

The documentation for this class was generated from the following files:
  • ipegeo.h
  • ipegeo.cpp

ipe-7.1.4/build/doc/structipe_1_1_style_sheet_1_1_title_style-members.html0000644000175000017500000001013412120621776026512 0ustar otfriedotfried Ipelib: Member List
ipe::StyleSheet::TitleStyle Member List

ipe-7.1.4/build/doc/classipe_1_1_pdf_parser-members.html0000644000175000017500000001104412120621776023010 0ustar otfriedotfried Ipelib: Member List
ipe::PdfParser Member List

This is the complete list of members for ipe::PdfParser, including all inherited members.

eos() const ipe::PdfParserinline
getChar()ipe::PdfParserinline
getObject()ipe::PdfParser
getObjectDef()ipe::PdfParser
getToken()ipe::PdfParser
getTrailer()ipe::PdfParser
PdfParser(DataSource &source)ipe::PdfParser
skipXRef()ipe::PdfParser
token() const ipe::PdfParserinline

ipe-7.1.4/build/doc/functions_func_0x77.html0000644000175000017500000001411112120621776020516 0ustar otfriedotfried Ipelib: Class Members - Functions
ipe-7.1.4/build/doc/luaobj.html0000644000175000017500000001752412120621776016175 0ustar otfriedotfried Ipelib: Lua bindings for objects and attributes
Lua bindings for objects and attributes

The five Ipe objects are ipe::Group, ipe::Path, ipe::Text, ipe::Image, and ipe::Reference. They can be constructed from Lua as follows:

obj = ipe.Reference(attributes, name, pos)
obj = ipe.Text(attributes, text, pos)          -- Text of type label
obj = ipe.Text(attributes, text, pos, width)   -- Text of type minipage
obj = ipe.Path(attributes, shape, with_arrows)   
obj = ipe.Group(elements)               -- elements is a table of objects

Here, attributes is a table defining the desired attributes, see below. shape is a table defining a shape, see below. To create path with arrows, you need to set with_arrows to true (it defaults to false). The arrow settings are then used from the attributes.

Objects have the following methods:

obj:type()    -- return type as string: group, text, path, image, reference
obj:clone()   -- clone the object

obj:set(property, value, stroke, fill) -- see below
obj:get(property)                -- see below

obj:xml()                        -- return XML representation
obj:matrix()
obj:setMatrix(m)
obj:addToBBox(r, m)              -- including control points
obj:addToBBox(r, m, false)       -- without control points

-- text and reference objects only:
v = obj:position()
-- text objects only:
obj:setText(str)
str = obj:text()
-- path objects only:
shape = obj:shape()                      
obj:setShape(shape)            
-- group objects only:
n = obj:count()                  
shape = obj:clip()           -- nil if no clipping
obj:setClip(shape)
-- image objects only:
obj:info()                   -- returns table about bitmap
-- group objects only:
elements = obj:elements()    -- returns table with clones of elements 

Attributes

Attributes are represented in Lua as follows:

  • Symbolic names are strings
  • Absolute string values (e.g. dash style) are strings
  • Absolute numeric values are numbers
  • Absolute colors are tables with three entries with keys r, g, b
  • Boolean values (for minipage, farrow, rarrow) are booleans (but the strings "true" and "false" can be used to set them)
  • Transformations, Pinned, Linejoin, Linecap, Fillrule, Horizontal alignment, and Vertical alignment are represented by fixed strings, see table below.

The attributes argument to the object constructors is a table defining all desired attributes. Keys in the table are as follows. If a key is not present, the default value is used.

pathmode -- "stroked", "strokedfilled", "filled"
stroke   -- symbolic or color
fill     -- symbolic or color
dashstyle -- symbolic or absolute string
pen      -- symbolic or number
farrow   -- boolean
rarrow   -- boolean
farrowshape -- symbolic
rarrowshape -- symbolic
arrowsize  -- symbolic or number
symbolsize -- symbolic or number
symbolshape -- symbolic
textsize   -- symbolic or number
transformableText -- boolean
textstyle  -- symbolic
opacity    -- symbolic
tiling     -- symbolic
minipage   -- boolean      
width      -- number
horizontalAlignment -- "left", "right", "hcenter"
verticalAlignment   -- "bottom", "baseline", "top", "vcenter"
linejoin            -- "normal", "miter", "round", "bevel"
linecap             -- "normal", "butt", "round", "square"
fillrule            -- "normal", "wind", "evenodd"
pinned              -- "none", "horizontal", "vertical", "fixed"
transformations     -- "translations", "rigid", "affine"

Properties

The set() and get() methods allow to access the attributes of objects. The property names are

    pen, symbolsize, 
    farrow, rarrow, farrowsize, rarrowsize, farrowshape, rarrowshape, 
    stroke, fill, markshape,
    pathmode, dashstyle, 
    textsize, textstyle, minipage, width, 
    opacity, tiling, gradient, 
    horizontalalignment, verticalalignment,
    linejoin, linecap, fillrule, 
    pinned, transformations, 

It is okay to set a property on objects that do not support them (for instance, "textsize" on a path object). Reading such properties results in an "undefined" return value.

The arguments stroke and fill for set are no longer used, and will disappear in the future.

Shape

The geometry of a path object and the clipping path of a group object is an ipe::Shape. This is represented in Lua as a pure Lua object, namely an array with one entry per subpath.

Each subpath is again a table with a type field whose value must be one of "ellipse", "closedspline", or "curve".

For an ellipse, element 1 of the table is the matrix.

For a closed spline, the table contains the control points.

For a curve, the table has a second field closed, which is either true or false. The table also has an entry for each segment of the curve. Each segment is again a table with a type field, whose value is one of "arc", "segment", "quad", "bezier", or "spline". The segment table contains the control points of the segment. For arc segments, there is an additional arc field in the segment table that contains the arc as an ipe.Arc object.


ipe-7.1.4/build/doc/classipe_1_1_curve.html0000644000175000017500000007653712120621776020401 0ustar otfriedotfried Ipelib: ipe::Curve Class Reference

#include <ipeshape.h>

Inherits ipe::SubPath.

Classes

struct  Seg

Public Member Functions

 Curve ()
virtual Type type () const
virtual bool closed () const
virtual const CurveasCurve () const
virtual void save (Stream &stream) const
virtual void draw (Painter &painter) const
virtual void addToBBox (Rect &box, const Matrix &m, bool cp) const
virtual double distance (const Vector &v, const Matrix &m, double bound) const
virtual void snapVtx (const Vector &mouse, const Matrix &m, Vector &pos, double &bound) const
virtual void snapBnd (const Vector &mouse, const Matrix &m, Vector &pos, double &bound) const
int countSegments () const
CurveSegment segment (int i) const
CurveSegment closingSegment (Vector u[2]) const
void appendSegment (const Vector &v0, const Vector &v1)
void appendArc (const Matrix &m, const Vector &v0, const Vector &v1)
void appendQuad (const Vector &v0, const Vector &v1, const Vector &v2)
void appendBezier (const Vector &v0, const Vector &v1, const Vector &v2, const Vector &v3)
void appendSpline (const std::vector< Vector > &v)
void setClosed (bool closed)
- Public Member Functions inherited from ipe::SubPath
virtual ~SubPath ()=0
virtual const EllipseasEllipse () const
virtual const ClosedSplineasClosedSpline () const

Additional Inherited Members

- Public Types inherited from ipe::SubPath
enum  Type { ECurve, EEllipse, EClosedSpline }

Detailed Description

Subpath consisting of a sequence of CurveSegment's.

Constructor & Destructor Documentation

Curve::Curve ( )

Create an empty, open subpath.

Member Function Documentation

SubPath::Type Curve::type ( ) const
virtual

Return type of this subpath.

Implements ipe::SubPath.

virtual bool ipe::Curve::closed ( ) const
inlinevirtual

Is this subpath closed?

Default implementation returns true.

Reimplemented from ipe::SubPath.

const Curve * Curve::asCurve ( ) const
virtual

Return this object as an Curve, or else 0.

Reimplemented from ipe::SubPath.

void Curve::save ( Stream stream) const
virtual

Save subpath to XML stream.

Implements ipe::SubPath.

void Curve::draw ( Painter painter) const
virtual

Draw subpath (does not call drawPath()).

Implements ipe::SubPath.

void Curve::addToBBox ( Rect box,
const Matrix m,
bool  cp 
) const
virtual

Add subpath to box.

Implements ipe::SubPath.

double Curve::distance ( const Vector v,
const Matrix m,
double  bound 
) const
virtual

Return distance from v to subpath transformed by m.

Implements ipe::SubPath.

void Curve::snapVtx ( const Vector mouse,
const Matrix m,
Vector pos,
double &  bound 
) const
virtual

Snap to vertex.

Implements ipe::SubPath.

void Curve::snapBnd ( const Vector mouse,
const Matrix m,
Vector pos,
double &  bound 
) const
virtual

Snap to boundary of subpath.

Implements ipe::SubPath.

int ipe::Curve::countSegments ( ) const
inline

Return number of segments. This does not include the closing segment for a closed path.

CurveSegment Curve::segment ( int  i) const

Return segment.

If i is negative, elements from the end are returned. The closing segment of a closed path is not accessible this way (use closingSegment() instead)!

CurveSegment Curve::closingSegment ( Vector  u[2]) const

Returns the closing segment of a closed path.

Since the closing segment isn't actually stored inside this object, you have to provide a length-2 vector for the control points.

This method panics if the Curve is not closed.

void Curve::appendSegment ( const Vector v0,
const Vector v1 
)

Append a straight segment to the subpath.

void Curve::appendArc ( const Matrix m,
const Vector v0,
const Vector v1 
)

Append elliptic arc to the subpath.

void Curve::appendQuad ( const Vector v0,
const Vector v1,
const Vector v2 
)

Append quadratic Bezier spline.

void Curve::appendBezier ( const Vector v0,
const Vector v1,
const Vector v2,
const Vector v3 
)

Append cubic Bezier spline.

void Curve::appendSpline ( const std::vector< Vector > &  v)

Append B-spline curve.

void Curve::setClosed ( bool  closed)

Set whether subpath is closed or not.


The documentation for this class was generated from the following files:
  • ipeshape.h
  • ipeshape.cpp

ipe-7.1.4/build/doc/ftv2cl.png0000644000175000017500000000070512120621776015732 0ustar otfriedotfried‰PNG  IHDRÚ}\ˆŒIDATxíÝ;H#AÇño4Љႇ œ„K‰‡‚á ’ê,m„ØØ vÚžJ°²¹ÚÎþî‚§ XY ÅB|dr³cvo—˜Ä°Ý ù0Ã’™3ÿͤõ”Ëe×´¸Éõ¯1XÞ8Œ‰nQˆ88ööÖ§3*rbñ¯¢û-$¨‚þ´˜“P1Žè@Z…-# Ïú01ÑÏÎêÄ1HkKŸ w¶O@¥ªÈóñ!f§ñu˜åác÷;’sá×Bý[E´Añ±—Í\ß>°ùý¿ÏËÊÂ]–P€zØf| Íñ¯“+Ù´gð5…b  i5ümM³œ_æÍq,ÒcŽõèoÓd´ !¶äò©ô•,ôðÀ{¹¨µYß,€zTÍ8H]𤕘ï7¼»/òó8ËQæ !F€~6ãá?Y ÀA@ŨÁ.@ƒ¶TäÄYïŠËë±r‘µ8Ð*·é>€Šçÿ?€×þŸe[6«xÂIEND®B`‚ipe-7.1.4/build/doc/manual_50.html0000644000175000017500000001032712120621776016474 0ustar otfriedotfried Ipe Manual -- 12.2 Environment variables
12 Command line options and environment variables12.1 Command line options12.2 Environment variables

12.2 Environment variables

Ipe, ipetoipe, and iperender respect the following environment variables:

IPELATEXDIR
the directory where Ipe runs Pdflatex.
IPEFONTMAP
the complete path of the font map, describing where Ipe can find the 14 standard pdf fonts.
IPEDEBUG
set to 1 for debugging output.
IPEANCIENTPDFTEX
set this variable to use Pdftex versions older than 1.40.

The Ipe program uses several additional environment variables:

EDITOR
external editor to use for editing text objects.
IPESTYLES
a list of directories, separated by semicolons, where Ipe looks for stylesheets, for instance for the standard stylesheet basic.isy. You can write _ (a single underscore) for the system-wide stylesheet directory. If this variable is not set, the default consists of the system-wide stylesheet directory, plus ~/.ipe/styles on Unix, plus ~/Library/Ipe/Styles on OS X.
IPELETPATH
a list of directories, separated by semicolons, containing ipelets. You can write _ (a single underscore) for the system-wide ipelet directory. If this variable is not set, the default consists of the system-wide ipelet directory, plus ~/.ipe/ipelets on Unix, plus ~/Library/Ipe/Ipelets on OS X.
IPEICONDIR
directory containing icons for the Ipe user interface.
IPEDOCDIR
directory containing Ipe documentation.
IPELUAPATH
path for searching for Ipe Lua code.
ipe-7.1.4/build/doc/functions_func_0x7e.html0000644000175000017500000002163412120621776020604 0ustar otfriedotfried Ipelib: Class Members - Functions
 

- ~ -


ipe-7.1.4/build/doc/classipe_1_1_curve_segment-members.html0000644000175000017500000002012112120621776023525 0ustar otfriedotfried Ipelib: Member List
ipe::CurveSegment Member List

This is the complete list of members for ipe::CurveSegment, including all inherited members.

addToBBox(Rect &box, const Matrix &m, bool cp) const ipe::CurveSegment
arc() const ipe::CurveSegment
bezier() const ipe::CurveSegment
beziers(std::vector< Bezier > &bez) const ipe::CurveSegment
countCP() const ipe::CurveSegmentinline
cp(int i) const ipe::CurveSegmentinline
Curve classipe::CurveSegmentfriend
distance(const Vector &v, const Matrix &m, double bound) const ipe::CurveSegment
draw(Painter &painter) const ipe::CurveSegment
EArc enum valueipe::CurveSegment
EBezier enum valueipe::CurveSegment
EQuad enum valueipe::CurveSegment
ESegment enum valueipe::CurveSegment
ESpline enum valueipe::CurveSegment
last() const ipe::CurveSegmentinline
matrix() const ipe::CurveSegmentinline
snapBnd(const Vector &mouse, const Matrix &m, Vector &pos, double &bound) const ipe::CurveSegment
snapVtx(const Vector &mouse, const Matrix &m, Vector &pos, double &bound) const ipe::CurveSegment
Type enum nameipe::CurveSegment
type() const ipe::CurveSegmentinline

ipe-7.1.4/build/doc/closed.png0000644000175000017500000000020412120621776015775 0ustar otfriedotfried‰PNG  IHDR à‘KIDATxíÝm @!†ÑGk™É7À-`&séts¦Àñþòð@åk}ª2€… P%Á_Ëþ¿N² .:0Dk¥‹Â›x" Ö›)¡xÒ5õIEND®B`‚ipe-7.1.4/build/doc/classipe_1_1_path-members.html0000644000175000017500000005617312120621776021633 0ustar otfriedotfried Ipelib: Member List
ipe::Path Member List

This is the complete list of members for ipe::Path, including all inherited members.

accept(Visitor &visitor) const ipe::Pathvirtual
addToBBox(Rect &box, const Matrix &m, bool cp) const ipe::Pathvirtual
arrow() const ipe::Pathinline
arrowShape() const ipe::Pathinline
arrowSize() const ipe::Pathinline
asGroup()ipe::Objectvirtual
asImage()ipe::Objectvirtual
asPath()ipe::Pathvirtual
asReference()ipe::Objectvirtual
asText()ipe::Objectvirtual
checkStyle(const Cascade *sheet, AttributeSeq &seq) const ipe::Pathvirtual
checkSymbol(Kind kind, Attribute attr, const Cascade *sheet, AttributeSeq &seq)ipe::Objectprotectedstatic
clone() const ipe::Pathvirtual
create(const XmlAttributes &attr, String data)ipe::Pathstatic
dashStyle() const ipe::Pathinline
distance(const Vector &v, const Matrix &m, double bound) const ipe::Pathvirtual
draw(Painter &painter) const ipe::Pathvirtual
drawArrow(Painter &painter, Vector pos, Angle alpha, Attribute shape, Attribute size, double radius)ipe::Pathstatic
drawSimple(Painter &painter) const ipe::Pathvirtual
EGroup enum valueipe::Object
EImage enum valueipe::Object
EPath enum valueipe::Object
EReference enum valueipe::Object
EText enum valueipe::Object
fill() const ipe::Pathinline
fillRule() const ipe::Pathinline
getAttribute(Property prop)ipe::Pathvirtual
gradient() const ipe::Pathinline
iMatrixipe::Objectprotected
iPinnedipe::Objectprotected
iTransformationsipe::Objectprotected
lineCap() const ipe::Pathinline
lineJoin() const ipe::Pathinline
matrix() const ipe::Objectinline
Object()ipe::Objectexplicitprotected
Object(const AllAttributes &attr)ipe::Objectexplicitprotected
Object(const Object &rhs)ipe::Objectprotected
Object(const XmlAttributes &attr)ipe::Objectexplicitprotected
opacity() const ipe::Pathinline
Path(const AllAttributes &attr, const Shape &shape, bool withArrows=false)ipe::Pathexplicit
pathMode() const ipe::Pathinline
pen() const ipe::Pathinline
pinned() const ipe::Objectvirtual
rArrow() const ipe::Pathinline
rArrowShape() const ipe::Pathinline
rArrowSize() const ipe::Pathinline
saveAsXml(Stream &stream, String layer) const ipe::Pathvirtual
saveAttributesAsXml(Stream &stream, String layer) const ipe::Objectprotected
setArrow(bool arrow, Attribute shape, Attribute size)ipe::Path
setAttribute(Property prop, Attribute value, Attribute stroke, Attribute fill)ipe::Pathvirtual
setDashStyle(Attribute dash)ipe::Path
setFill(Attribute fill)ipe::Path
setFillRule(TFillRule s)ipe::Path
setGradient(Attribute a)ipe::Path
setLineCap(TLineCap s)ipe::Path
setLineJoin(TLineJoin s)ipe::Path
setMatrix(const Matrix &matrix)ipe::Object
setOpacity(Attribute opaq)ipe::Path
setPathMode(TPathMode pm)ipe::Path
setPen(Attribute pen)ipe::Path
setPinned(TPinned pin)ipe::Object
setRarrow(bool arrow, Attribute shape, Attribute size)ipe::Path
setShape(const Shape &shape)ipe::Path
setStroke(Attribute stroke)ipe::Path
setTiling(Attribute a)ipe::Path
setTransformations(TTransformations trans)ipe::Object
shape() const ipe::Pathinline
snapBnd(const Vector &mouse, const Matrix &m, Vector &pos, double &bound) const ipe::Pathvirtual
snapVtx(const Vector &mouse, const Matrix &m, Vector &pos, double &bound) const ipe::Pathvirtual
stroke() const ipe::Pathinline
tiling() const ipe::Pathinline
transformations() const ipe::Objectinline
type() const ipe::Pathvirtual
Type enum nameipe::Object
~Object()=0ipe::Objectpure virtual

ipe-7.1.4/build/doc/classipe_1_1_pdf_obj-members.html0000644000175000017500000001230712120621776022271 0ustar otfriedotfried Ipelib: Member List
ipe::PdfObj Member List

This is the complete list of members for ipe::PdfObj, including all inherited members.

array() const ipe::PdfObjvirtual
boolean() const ipe::PdfObjvirtual
dict() const ipe::PdfObjvirtual
name() const ipe::PdfObjvirtual
null() const ipe::PdfObjvirtual
number() const ipe::PdfObjvirtual
ref() const ipe::PdfObjvirtual
repr() const ipe::PdfObj
string() const ipe::PdfObjvirtual
write(Stream &stream) const =0ipe::PdfObjpure virtual
~PdfObj()=0ipe::PdfObjpure virtual

ipe-7.1.4/build/doc/functions_type.html0000644000175000017500000000537212120621776017770 0ustar otfriedotfried Ipelib: Class Members - Typedefs
 

ipe-7.1.4/build/doc/functions_func_0x62.html0000644000175000017500000001724012120621776020516 0ustar otfriedotfried Ipelib: Class Members - Functions
 

- b -


ipe-7.1.4/build/doc/ftv2folderclosed.png0000644000175000017500000000115012120621776017774 0ustar otfriedotfried‰PNG  IHDRÚ}\ˆ/IDATxí]MOÔ@~ÚúuØlp]ö¿#›Å]PYECˆ\9ù¼yÑß`ÖÄÿàÿÀÉxóâ¢C &=qÐÄ£—vZçv¶3m؃‡vžLûNç}Þ÷}Þ½ZA@n° OäNp ’xóþK°ññ€xÜj”°8sÑ€“ “€œ_¼[Âíæ§ïD'‚•yye+ø¼û 7#rNŸlïük* ¾0Ь_d«_(àñÖ±àôz=ñxõv§÷h©‰z¹€šØP-äóä’̪uý¼$»\DãJc—B4¯ãÝÖ.:£Ï-ÑÏß}µŠLEíºþ #—ûáºÀÏgN;BŠ€6ïýñ䬜…ö@’Ðåñp&™h>p9¤™EEά¨ÎÊ‘" u¥n€$R"?{¹<˜…ë…%PNtâ$‰ß¶±úá+^<é"§2 ªDq”q´\¬«Ò™a–Œ‘©Aÿ€"Ôµ ™êŸèP£}#Eàz{û.8i îp³ê(ADwD¦E<ê¬cE¦$ HdÊÄ ”.:Ù GŽ-`ŒL‚ý¾'¢‰Ä<¤CIª½;ÙÇTZd±i};>èôß‚z×;K×§8t ¤Ž q”:uvÿv•Ý›¬²ÙvEân{„M·FXg¼ÌfZÖ¨°¹‰*›ßÌß©±ù©:›j–YqèÜë#3çÏSøWøÿÿÑr'ø Ôùù‚ ©¡IEND®B`‚ipe-7.1.4/build/doc/namespaceipe.html0000644000175000017500000016632412120621776017356 0ustar otfriedotfried Ipelib: ipe Namespace Reference
ipe Namespace Reference

Classes

class  Color
 An absolute RGB color. More...
struct  Tiling
 A tiling pattern. More...
struct  Gradient
 A gradient pattern. More...
struct  Layout
 Layout of a Page. More...
struct  TextPadding
 Padding for text bounding box. More...
class  Effect
 Effect that Acrobat Reader will show on page change. More...
class  Repository
 Repository of strings. More...
class  Attribute
 An attribute of an Ipe Object. More...
class  AllAttributes
 Collection of all object attributes. More...
class  String
 Strings and buffers. More...
class  Fixed
 Fixed point number with three (decimal) fractional digits. More...
class  Lex
 Lexical analyser. Seeded with a string. More...
class  Buffer
 A memory buffer. More...
class  Stream
 Abstract base class for output streams. More...
class  TellStream
 Adds position feedback to IpeStream. More...
class  StringStream
 Stream writing into an String. More...
class  FileStream
 Stream writing into an open file. More...
class  DataSource
 Interface for getting data for parsing. More...
class  FileSource
 Data source for parsing from a file. More...
class  BufferSource
 Data source for parsing from a buffer. More...
class  Platform
 Platform dependent methods. More...
class  Bitmap
 A bitmap. More...
class  Document
 The model for an Ipe document. More...
class  ObjectFactory
 Factory for Ipe leaf objects. More...
struct  Font
 A text font. More...
class  Angle
 A double that's an angle. More...
class  Vector
 Two-dimensional vector. More...
class  Rect
 Axis-parallel rectangle (which can be empty) More...
class  Line
 A directed line. More...
class  Segment
 A directed line segment. More...
class  Bezier
 A cubic Bezier spline. More...
class  Linear
 Linear transformation in the plane (2x2 matrix). More...
class  Matrix
 Homogeneous transformation in the plane. More...
class  Arc
 An arc of an ellipse. More...
class  Group
 The group object. More...
class  Image
 The image object. More...
class  ImlParser
 XML Parser for Ipe documents and style sheets. More...
class  Latex
 Object that converts latex source to PDF format. More...
class  IpeletHelper
 Service provider for Ipelets. More...
struct  IpeletData
 Information provided to an ipelet when it is run. More...
class  Ipelet
 Abstract base class for Ipelets. More...
class  Object
 Base class for all Ipe objects, composite or leaf. More...
class  Visitor
 Base class for visitors to Object. More...
class  Page
 An Ipe document page. More...
class  Painter
 Interface for drawing. More...
class  Path
 The path object (polylines, polygons, and generalizations). More...
class  PdfObj
 Abstract base class for PDF objects. More...
class  PdfNull
 The PDF null object. More...
class  PdfBool
 The PDF bool object. More...
class  PdfNumber
 The PDF number object. More...
class  PdfString
 The PDF string object. More...
class  PdfName
 The PDF name object. More...
class  PdfRef
 The PDF reference object (indirect object). More...
class  PdfArray
 The PDF array object. More...
class  PdfDict
 The PDF dictionary and stream objects. More...
struct  PdfToken
 A PDF lexical token. More...
class  PdfParser
 PDF parser. More...
class  PdfFile
 All information obtained by parsing a PDF file. More...
class  PdfPainter
class  PdfWriter
 Create PDF file. More...
class  PsPainter
class  PsWriter
 Create Postscript file. More...
class  Reference
 The reference object. More...
class  CurveSegment
 A segment on an SubPath. More...
class  SubPath
 A subpath of a Path. More...
class  Ellipse
 An ellipse subpath. More...
class  ClosedSpline
 A closed B-spline curve. More...
class  Curve
 Subpath consisting of a sequence of CurveSegment's. More...
class  Shape
 A geometric shape, consisting of several (open or closed) subpaths. More...
class  Snap
 Performs snapping operations, and stores snapping state. More...
class  Symbol
 A symbol is a named object defined in an ipe::StyleSheet. More...
class  StyleSheet
 A style sheet maps symbolic names to absolute values. More...
class  Cascade
 A cascade of style sheets. More...
class  Text
 The text object. More...
class  BitmapFinder
 A visitor that recursively scans objects and collects all bitmaps. More...
class  BBoxPainter
 Paint objects using this painter to compute an accurate bounding box. More...
class  A85Stream
 Filter stream adding ASCII85 encoding. More...
class  Base64Stream
 Filter stream adding Base64 encoding. More...
class  DeflateStream
 Filter stream adding flate compression. More...
class  A85Source
 Filter source adding ASCII85 decoding. More...
class  Base64Source
 Filter source adding Base64 decoding. More...
class  InflateSource
 Filter source adding flate decompression. More...
class  XmlAttributes
 Stores attributes of an XML tag. More...
class  XmlParser
 Base class for XML stream parsing. More...
class  CairoPainter
 Ipe Painter using Cairo and Freetype as a backend. More...
class  Face
 A typeface (aka font), actually loaded (from a font file or PDF file). More...
class  Fonts
 Provides the fonts used to render text. More...
class  Thumbnail
class  CanvasObserver
class  CanvasBase
class  Canvas
 A widget (control) that displays an Ipe document page. More...
class  PageSelector
class  Tool
 Abstract base class for various canvas tools. More...
class  PanTool
 A tool for panning the canvas. More...
class  SelectTool
 A tool for selecting objects. More...
class  TransformTool
 A tool for transforming the selected objects on the canvas. More...

Typedefs

typedef std::vector< AttributeAttributeSeq

Enumerations

enum  Kind {
  EPen = 0, ESymbolSize, EArrowSize, EColor,
  EDashStyle, ETextSize, ETextStretch, ETextStyle,
  EGridSize, EAngleSize, EOpacity, ETiling,
  ESymbol, EGradient, EEffect
}
enum  Property {
  EPropPen = 0, EPropSymbolSize, EPropFArrow, EPropRArrow,
  EPropFArrowSize, EPropRArrowSize, EPropFArrowShape, EPropRArrowShape,
  EPropStrokeColor, EPropFillColor, EPropMarkShape, EPropPathMode,
  EPropDashStyle, EPropTextSize, EPropTextStyle, EPropOpacity,
  EPropTiling, EPropGradient, EPropHorizontalAlignment, EPropVerticalAlignment,
  EPropLineJoin, EPropLineCap, EPropFillRule, EPropPinned,
  EPropTransformations, EPropTransformableText, EPropMinipage, EPropWidth
}
enum  TPathMode { EStrokedOnly, EStrokedAndFilled, EFilledOnly }
enum  THorizontalAlignment { EAlignLeft, EAlignRight, EAlignHCenter }
enum  TVerticalAlignment { EAlignBottom, EAlignBaseline, EAlignTop, EAlignVCenter }
enum  TLineJoin { EDefaultJoin, EMiterJoin, ERoundJoin, EBevelJoin }
enum  TLineCap { EDefaultCap, EButtCap, ERoundCap, ESquareCap }
enum  TFillRule { EDefaultRule, EWindRule, EEvenOddRule }
enum  TPinned { ENoPin = 0x00, EHorizontalPin = 0x01, EVerticalPin = 0x02, EFixedPin = 0x03 }
enum  TTransformations { ETransformationsTranslations, ETransformationsRigidMotions, ETransformationsAffine }
enum  TSelect { ENotSelected = 0, EPrimarySelected, ESecondarySelected }

Functions

template<class T >
max (const T &lhs, const T &rhs)
template<class T >
min (const T &lhs, const T &rhs)
double abs (double val)
QPointF QPt (const Vector &v)
String IpeQ (const QString &str)
QString QIpe (const String &str)
QColor QIpe (Color color)
Color IpeQ (QColor color)

Variables

const char *const kind_names []
const char *const property_names []
const int IPELIB_VERSION = 70104
const int OLDEST_FILE_FORMAT = 70000
const int FILE_FORMAT = 70005

Function Documentation

QPointF ipe::QPt ( const Vector &  v)
inline
String ipe::IpeQ ( const QString &  str)
inline
QString ipe::QIpe ( const String &  str)
inline
QColor ipe::QIpe ( Color  color)
inline
Color ipe::IpeQ ( QColor  color)
inline

ipe-7.1.4/build/doc/classipe_1_1_object-members.html0000644000175000017500000003365112120621776022141 0ustar otfriedotfried Ipelib: Member List
ipe::Object Member List

This is the complete list of members for ipe::Object, including all inherited members.

accept(Visitor &visitor) const =0ipe::Objectpure virtual
addToBBox(Rect &box, const Matrix &m, bool cp) const =0ipe::Objectpure virtual
asGroup()ipe::Objectvirtual
asImage()ipe::Objectvirtual
asPath()ipe::Objectvirtual
asReference()ipe::Objectvirtual
asText()ipe::Objectvirtual
checkStyle(const Cascade *sheet, AttributeSeq &seq) const ipe::Objectvirtual
checkSymbol(Kind kind, Attribute attr, const Cascade *sheet, AttributeSeq &seq)ipe::Objectprotectedstatic
clone() const =0ipe::Objectpure virtual
distance(const Vector &v, const Matrix &m, double bound) const =0ipe::Objectpure virtual
draw(Painter &painter) const =0ipe::Objectpure virtual
drawSimple(Painter &painter) const =0ipe::Objectpure virtual
EGroup enum valueipe::Object
EImage enum valueipe::Object
EPath enum valueipe::Object
EReference enum valueipe::Object
EText enum valueipe::Object
getAttribute(Property prop)ipe::Objectvirtual
iMatrixipe::Objectprotected
iPinnedipe::Objectprotected
iTransformationsipe::Objectprotected
matrix() const ipe::Objectinline
Object()ipe::Objectexplicitprotected
Object(const AllAttributes &attr)ipe::Objectexplicitprotected
Object(const Object &rhs)ipe::Objectprotected
Object(const XmlAttributes &attr)ipe::Objectexplicitprotected
pinned() const ipe::Objectvirtual
saveAsXml(Stream &stream, String layer) const =0ipe::Objectpure virtual
saveAttributesAsXml(Stream &stream, String layer) const ipe::Objectprotected
setAttribute(Property prop, Attribute value, Attribute stroke, Attribute fill)ipe::Objectvirtual
setMatrix(const Matrix &matrix)ipe::Object
setPinned(TPinned pin)ipe::Object
setTransformations(TTransformations trans)ipe::Object
snapBnd(const Vector &mouse, const Matrix &m, Vector &pos, double &bound) const ipe::Objectvirtual
snapVtx(const Vector &mouse, const Matrix &m, Vector &pos, double &bound) const =0ipe::Objectpure virtual
transformations() const ipe::Objectinline
Type enum nameipe::Object
type() const =0ipe::Objectpure virtual
~Object()=0ipe::Objectpure virtual

ipe-7.1.4/build/doc/namespaces.html0000644000175000017500000000340112120621776017025 0ustar otfriedotfried Ipelib: Namespace List

Namespace List

Here is a list of all namespaces with brief descriptions:
ipeIpe library namespace
ipeqt

ipe-7.1.4/build/doc/functions.html0000644000175000017500000003276712120621776016737 0ustar otfriedotfried Ipelib: Class Members
Here is a list of all class members with links to the classes they belong to:

- a -


ipe-7.1.4/build/doc/classipe_1_1_cascade.html0000644000175000017500000007104612120621776020626 0ustar otfriedotfried Ipelib: ipe::Cascade Class Reference

#include <ipestyle.h>

Public Member Functions

 Cascade ()
 Cascade (const Cascade &rhs)
Cascadeoperator= (const Cascade &rhs)
 ~Cascade ()
int count () const
StyleSheetsheet (int index)
void insert (int index, StyleSheet *sheet)
void remove (int index)
void saveAsXml (Stream &stream) const
bool has (Kind kind, Attribute sym) const
Attribute find (Kind, Attribute sym) const
const SymbolfindSymbol (Attribute sym) const
const GradientfindGradient (Attribute sym) const
const TilingfindTiling (Attribute sym) const
const EffectfindEffect (Attribute sym) const
const LayoutfindLayout () const
const TextPaddingfindTextPadding () const
const StyleSheet::TitleStylefindTitleStyle () const
const StyleSheet::PageNumberStylefindPageNumberStyle () const
String findPreamble () const
String findEncoding () const
TLineCap lineCap () const
TLineJoin lineJoin () const
TFillRule fillRule () const
void allNames (Kind kind, AttributeSeq &seq) const
int findDefinition (Kind kind, Attribute sym) const
void allCMaps (std::vector< String > &seq) const

Detailed Description

A cascade of style sheets.

The StyleSheets of a document cascade in the sense that a document can refer to several StyleSheets, which are arranged in a stack. A lookup is done from top to bottom, and returns as soon as a match is found. Ipe always appends the built-in "standard" style sheet at the bottom of the cascade.

Constructor & Destructor Documentation

Cascade::Cascade ( )

Create an empty cascade.

This does not add the standard style sheet.

Cascade::Cascade ( const Cascade rhs)

Copy constructor.

Cascade::~Cascade ( )

Destructor.

Member Function Documentation

Cascade & Cascade::operator= ( const Cascade rhs)

Assignment operator.

int ipe::Cascade::count ( ) const
inline

Return number of style sheets.

StyleSheet* ipe::Cascade::sheet ( int  index)
inline

Return StyleSheet at index.

void Cascade::insert ( int  index,
StyleSheet sheet 
)

Insert a style sheet into the cascade.

Takes ownership of sheet.

void Cascade::remove ( int  index)

Remove a style sheet from the cascade.

The old sheet is deleted.

void Cascade::saveAsXml ( Stream stream) const
bool Cascade::has ( Kind  kind,
Attribute  sym 
) const
Attribute Cascade::find ( Kind  kind,
Attribute  sym 
) const
const Symbol * Cascade::findSymbol ( Attribute  sym) const
const Gradient * Cascade::findGradient ( Attribute  sym) const
const Tiling * Cascade::findTiling ( Attribute  sym) const
const Effect * Cascade::findEffect ( Attribute  sym) const
const Layout * Cascade::findLayout ( ) const

Find page layout (such as text margins).

const TextPadding * Cascade::findTextPadding ( ) const

Find text padding (for text bbox computation).

const StyleSheet::TitleStyle * Cascade::findTitleStyle ( ) const

Get style of page titles (or 0 if none defined).

const StyleSheet::PageNumberStyle * Cascade::findPageNumberStyle ( ) const

Return style of page numbering (or 0 if none defined).

String Cascade::findPreamble ( ) const

Return total LaTeX preamble (of the whole cascade).

String Cascade::findEncoding ( ) const

Return LaTeX encoding (of the whole cascade).

TLineCap Cascade::lineCap ( ) const
TLineJoin Cascade::lineJoin ( ) const
TFillRule Cascade::fillRule ( ) const
void Cascade::allNames ( Kind  kind,
AttributeSeq seq 
) const
int Cascade::findDefinition ( Kind  kind,
Attribute  sym 
) const

Find stylesheet defining the attribute.

This method goes through the cascade looking for a definition of the symbolic attribute sym. It returns the index of the stylesheet defining the attribute, or -1 if the attribute is not defined.

The method panics if sym is not symbolic. It also works for ESymbol, EGradient, ETiling, and EEffect.

void Cascade::allCMaps ( std::vector< String > &  seq) const

The documentation for this class was generated from the following files:
  • ipestyle.h
  • ipestyle.cpp

ipe-7.1.4/build/doc/classipe_1_1_vector-members.html0000644000175000017500000002216112120621776022167 0ustar otfriedotfried Ipelib: Member List
ipe::Vector Member List

This is the complete list of members for ipe::Vector, including all inherited members.

angle() const ipe::Vector
dot(const Vector &lhs, const Vector &rhs)ipe::Vectorrelated
factorize(Vector &unit) const ipe::Vector
len() const ipe::Vector
normalized() const ipe::Vector
operator!=(const Vector &rhs) const ipe::Vectorinline
operator*(double rhs) const ipe::Vectorinline
operator*(double lhs, const Vector &rhs)ipe::Vectorrelated
operator*=(double rhs)ipe::Vectorinline
operator+(const Vector &rhs) const ipe::Vectorinline
operator+=(const Vector &rhs)ipe::Vectorinline
operator-(const Vector &rhs) const ipe::Vectorinline
operator-() const ipe::Vectorinline
operator-=(const Vector &rhs)ipe::Vectorinline
operator<<(Stream &stream, const Vector &rhs)ipe::Vectorrelated
operator==(const Vector &rhs) const ipe::Vectorinline
orthogonal() const ipe::Vector
snap(const Vector &mouse, Vector &pos, double &bound) const ipe::Vector
sqLen() const ipe::Vectorinline
Vector()ipe::Vectorinline
Vector(Angle alpha)ipe::Vectorexplicit
Vector(double x0, double y0)ipe::Vectorinlineexplicit
xipe::Vector
yipe::Vector
ZEROipe::Vectorstatic

ipe-7.1.4/build/doc/manual_10.html0000644000175000017500000000716012120621776016471 0ustar otfriedotfried Ipe Manual -- 3.7 Symbolic and absolute attributes
3.8 Zoom and pan3 General Concepts3.6 Transparency3.7 Symbolic and absolute attributes

3.7 Symbolic and absolute attributes

Attributes such as color, line width, pen, mark size, or text size, can be either absolute (a number, or a set of numbers specifying a color) or symbolic (a name). Symbolic attributes must be translated to absolute values by a stylesheet for rendering.

One purpose of stylesheets is to be able to reuse figures from articles in presentations. Obviously, the figure has to use much larger fonts, markers, arrows, and fatter lines in the presentation. If the original figure used symbolic attributes, this can be achieved by simply swapping the stylesheet for another one.

The Ipe user interface is tuned for using symbolic attribute values. You can use absolute colors, pen width, text size, and mark size by clicking the button to the left of the selector for the symbolic names.

When creating an object, it takes its attributes from the current user interface settings, so if you have selected an absolute value, it will get an absolute attribute. Absolute attributes have the advantage that you are free to choose any value you wish, including picking arbitrary colors using a color chooser. In symbolic mode, you can only use the choices provided by the current stylesheet.

The choices for symbolic attributes provided in the Ipe user interface are taken from your stylesheet.

ipe-7.1.4/build/doc/ipe.dtd0000644000175000017500000001321212120621776015273 0ustar otfriedotfried ipe-7.1.4/build/doc/functions_func_0x76.html0000644000175000017500000001431512120621776020523 0ustar otfriedotfried Ipelib: Class Members - Functions
 

- v -


ipe-7.1.4/build/doc/classipe_1_1_arc-members.html0000644000175000017500000001531712120621776021437 0ustar otfriedotfried Ipelib: Member List
ipe::Arc Member List

This is the complete list of members for ipe::Arc, including all inherited members.

Arc()ipe::Arcinline
Arc(const Matrix &m, Angle alpha, Angle beta)ipe::Arcinline
Arc(const Matrix &m)ipe::Arcinline
Arc(const Matrix &m0, const Vector &begp, const Vector &endp)ipe::Arc
bbox() const ipe::Arc
beginp() const ipe::Arcinline
distance(const Vector &v, double bound) const ipe::Arc
distance(const Vector &v, double bound, Vector &pos, Angle &angle) const ipe::Arc
endp() const ipe::Arcinline
iAlphaipe::Arc
iBetaipe::Arc
iMipe::Arc
intersect(const Line &l, std::vector< Vector > &result) const ipe::Arc
intersect(const Segment &s, std::vector< Vector > &result) const ipe::Arc
intersect(const Arc &a, std::vector< Vector > &result) const ipe::Arc
intersect(const Bezier &b, std::vector< Vector > &result) const ipe::Arc
isEllipse() const ipe::Arcinline

ipe-7.1.4/build/doc/radgrad1.svg0000644000175000017500000000237012120621776016232 0ustar otfriedotfried ipe-7.1.4/build/doc/classipe_1_1_group-members.html0000644000175000017500000004301012120621776022015 0ustar otfriedotfried Ipelib: Member List
ipe::Group Member List

This is the complete list of members for ipe::Group, including all inherited members.

accept(Visitor &visitor) const ipe::Groupvirtual
addToBBox(Rect &box, const Matrix &m, bool cp) const ipe::Groupvirtual
asGroup()ipe::Groupvirtual
asImage()ipe::Objectvirtual
asPath()ipe::Objectvirtual
asReference()ipe::Objectvirtual
asText()ipe::Objectvirtual
begin() const ipe::Groupinline
checkStyle(const Cascade *sheet, AttributeSeq &seq) const ipe::Groupvirtual
checkSymbol(Kind kind, Attribute attr, const Cascade *sheet, AttributeSeq &seq)ipe::Objectprotectedstatic
clip() const ipe::Groupinline
clone() const ipe::Groupvirtual
const_iterator typedefipe::Group
count() const ipe::Groupinline
distance(const Vector &v, const Matrix &m, double bound) const ipe::Groupvirtual
draw(Painter &painter) const ipe::Groupvirtual
drawSimple(Painter &painter) const ipe::Groupvirtual
EGroup enum valueipe::Object
EImage enum valueipe::Object
end() const ipe::Groupinline
EPath enum valueipe::Object
EReference enum valueipe::Object
EText enum valueipe::Object
getAttribute(Property prop)ipe::Objectvirtual
Group()ipe::Groupexplicit
Group(const Group &rhs)ipe::Group
Group(const XmlAttributes &attr)ipe::Groupexplicit
iMatrixipe::Objectprotected
iPinnedipe::Objectprotected
iTransformationsipe::Objectprotected
matrix() const ipe::Objectinline
Object()ipe::Objectexplicitprotected
Object(const AllAttributes &attr)ipe::Objectexplicitprotected
Object(const Object &rhs)ipe::Objectprotected
Object(const XmlAttributes &attr)ipe::Objectexplicitprotected
object(int i) const ipe::Groupinline
operator=(const Group &rhs)ipe::Group
pinned() const ipe::Groupvirtual
push_back(Object *)ipe::Group
saveAsXml(Stream &stream, String layer) const ipe::Groupvirtual
saveAttributesAsXml(Stream &stream, String layer) const ipe::Objectprotected
saveComponentsAsXml(Stream &stream) const ipe::Group
setAttribute(Property prop, Attribute value, Attribute stroke, Attribute fill)ipe::Groupvirtual
setClip(const Shape &clip)ipe::Group
setMatrix(const Matrix &matrix)ipe::Object
setPinned(TPinned pin)ipe::Object
setTransformations(TTransformations trans)ipe::Object
snapBnd(const Vector &mouse, const Matrix &m, Vector &pos, double &bound) const ipe::Groupvirtual
snapVtx(const Vector &mouse, const Matrix &m, Vector &pos, double &bound) const ipe::Groupvirtual
transformations() const ipe::Objectinline
Type enum nameipe::Object
type() const ipe::Groupvirtual
~Group()ipe::Groupvirtual
~Object()=0ipe::Objectpure virtual

ipe-7.1.4/build/doc/manual_53.html0000644000175000017500000003022012120621776016471 0ustar otfriedotfried Ipe Manual -- Contents
FootnotesTop14 CopyrightContents

Contents

ipe-7.1.4/build/doc/classipe_1_1_cairo_painter-members.html0000644000175000017500000005516112120621776023512 0ustar otfriedotfried Ipelib: Member List
ipe::CairoPainter Member List

This is the complete list of members for ipe::CairoPainter, including all inherited members.

addClipPath()ipe::Painter
CairoPainter(const Cascade *sheet, Fonts *fonts, cairo_t *cc, double zoom, bool pretty)ipe::CairoPainter
cascade() const ipe::Painterinline
closePath()ipe::Painter
curveTo(const Vector &v1, const Vector &v2, const Vector &v3)ipe::Painter
curveTo(const Bezier &bezier)ipe::Painterinline
dashStyle() const ipe::Painterinline
dashStyle(std::vector< double > &dashes, double &offset) const ipe::Painter
doAddClipPath()ipe::CairoPainterprotectedvirtual
doClosePath()ipe::CairoPainterprotectedvirtual
doCurveTo(const Vector &v1, const Vector &v2, const Vector &v3)ipe::CairoPainterprotectedvirtual
doDrawArc(const Arc &arc)ipe::CairoPainterprotectedvirtual
doDrawBitmap(Bitmap bitmap)ipe::CairoPainterprotectedvirtual
doDrawPath(TPathMode mode)ipe::CairoPainterprotectedvirtual
doDrawSymbol(Attribute symbol)ipe::Painterprotectedvirtual
doDrawText(const Text *text)ipe::CairoPainterprotectedvirtual
doLineTo(const Vector &v)ipe::CairoPainterprotectedvirtual
doMoveTo(const Vector &v)ipe::CairoPainterprotectedvirtual
doNewPath()ipe::Painterprotectedvirtual
doPop()ipe::CairoPainterprotectedvirtual
doPush()ipe::CairoPainterprotectedvirtual
drawArc(const Arc &arc)ipe::Painter
drawArcAsBezier(double alpha)ipe::Painterprotected
drawBitmap(Bitmap bitmap)ipe::Painter
drawEllipse()ipe::Painter
drawPath(TPathMode mode)ipe::Painter
drawSymbol(Attribute symbol)ipe::Painter
drawText(const Text *text)ipe::Painter
fill() const ipe::Painterinline
fillRule() const ipe::Painterinline
gradient() const ipe::Painterinline
iCascadeipe::Painterprotected
iInPathipe::Painterprotected
iMatrixipe::Painterprotected
iStateipe::Painterprotected
lineCap() const ipe::Painterinline
lineJoin() const ipe::Painterinline
lineTo(const Vector &v)ipe::Painter
matrix() const ipe::Painterinline
moveTo(const Vector &v)ipe::Painter
newPath()ipe::Painter
opacity() const ipe::Painterinline
Painter(const Cascade *style)ipe::Painter
pen() const ipe::Painterinline
pop()ipe::Painter
popMatrix()ipe::Painter
push()ipe::Painter
pushMatrix()ipe::Painter
rect(const Rect &re)ipe::Painter
setDashStyle(Attribute dash)ipe::Painter
setDimmed(bool dim)ipe::CairoPainterinline
setFill(Attribute color)ipe::Painter
setFillRule(TFillRule rule)ipe::Painter
setGradient(Attribute grad)ipe::Painter
setLineCap(TLineCap cap)ipe::Painter
setLineJoin(TLineJoin join)ipe::Painter
setOpacity(Attribute opaq)ipe::Painter
setPen(Attribute pen)ipe::Painter
setStroke(Attribute color)ipe::Painter
setSymFill(Attribute color)ipe::Painter
setSymPen(Attribute wid)ipe::Painter
setSymStroke(Attribute color)ipe::Painter
setTiling(Attribute til)ipe::Painter
stroke() const ipe::Painterinline
symFill() const ipe::Painterinline
symPen() const ipe::Painterinline
symStroke() const ipe::Painterinline
tiling() const ipe::Painterinline
transform(const Matrix &m)ipe::Painter
translate(const Vector &v)ipe::Painter
untransform(TTransformations trans)ipe::Painter
~CairoPainter()ipe::CairoPainterinlinevirtual
~Painter()ipe::Paintervirtual

ipe-7.1.4/build/doc/namespacemembers_eval.html0000644000175000017500000003065412120621776021236 0ustar otfriedotfried Ipelib: Namespace Members
 

- e -

  • EAlignBaseline : ipe
  • EAlignBottom : ipe
  • EAlignHCenter : ipe
  • EAlignLeft : ipe
  • EAlignRight : ipe
  • EAlignTop : ipe
  • EAlignVCenter : ipe
  • EAngleSize : ipe
  • EArrowSize : ipe
  • EBevelJoin : ipe
  • EButtCap : ipe
  • EColor : ipe
  • EDashStyle : ipe
  • EDefaultCap : ipe
  • EDefaultJoin : ipe
  • EDefaultRule : ipe
  • EEffect : ipe
  • EEvenOddRule : ipe
  • EFilledOnly : ipe
  • EFixedPin : ipe
  • EGradient : ipe
  • EGridSize : ipe
  • EHorizontalPin : ipe
  • EMiterJoin : ipe
  • ENoPin : ipe
  • ENotSelected : ipe
  • EOpacity : ipe
  • EPen : ipe
  • EPrimarySelected : ipe
  • EPropDashStyle : ipe
  • EPropFArrow : ipe
  • EPropFArrowShape : ipe
  • EPropFArrowSize : ipe
  • EPropFillColor : ipe
  • EPropFillRule : ipe
  • EPropGradient : ipe
  • EPropHorizontalAlignment : ipe
  • EPropLineCap : ipe
  • EPropLineJoin : ipe
  • EPropMarkShape : ipe
  • EPropMinipage : ipe
  • EPropOpacity : ipe
  • EPropPathMode : ipe
  • EPropPen : ipe
  • EPropPinned : ipe
  • EPropRArrow : ipe
  • EPropRArrowShape : ipe
  • EPropRArrowSize : ipe
  • EPropStrokeColor : ipe
  • EPropSymbolSize : ipe
  • EPropTextSize : ipe
  • EPropTextStyle : ipe
  • EPropTiling : ipe
  • EPropTransformableText : ipe
  • EPropTransformations : ipe
  • EPropVerticalAlignment : ipe
  • EPropWidth : ipe
  • ERoundCap : ipe
  • ERoundJoin : ipe
  • ESecondarySelected : ipe
  • ESquareCap : ipe
  • EStrokedAndFilled : ipe
  • EStrokedOnly : ipe
  • ESymbol : ipe
  • ESymbolSize : ipe
  • ETextSize : ipe
  • ETextStretch : ipe
  • ETextStyle : ipe
  • ETiling : ipe
  • ETransformationsAffine : ipe
  • ETransformationsRigidMotions : ipe
  • ETransformationsTranslations : ipe
  • EVerticalPin : ipe
  • EWindRule : ipe

ipe-7.1.4/build/doc/classipe_1_1_effect-members.html0000644000175000017500000002060412120621776022121 0ustar otfriedotfried Ipelib: Member List
ipe::Effect Member List

This is the complete list of members for ipe::Effect, including all inherited members.

EBlindsH enum valueipe::Effect
EBlindsV enum valueipe::Effect
EBoxI enum valueipe::Effect
EBoxO enum valueipe::Effect
EDissolve enum valueipe::Effect
Effect()ipe::Effect
EGlitterD enum valueipe::Effect
EGlitterLR enum valueipe::Effect
EGlitterTB enum valueipe::Effect
ENormal enum valueipe::Effect
ESplitHI enum valueipe::Effect
ESplitHO enum valueipe::Effect
ESplitVI enum valueipe::Effect
ESplitVO enum valueipe::Effect
EWipeBT enum valueipe::Effect
EWipeLR enum valueipe::Effect
EWipeRL enum valueipe::Effect
EWipeTB enum valueipe::Effect
iDurationipe::Effect
iEffectipe::Effect
iTransitionTimeipe::Effect
pageDictionary(Stream &stream) const ipe::Effect
TEffect enum nameipe::Effect

ipe-7.1.4/build/doc/classipe_1_1_pdf_writer-members.html0000644000175000017500000001016012120621776023026 0ustar otfriedotfried Ipelib: Member List
ipe::PdfWriter Member List

This is the complete list of members for ipe::PdfWriter, including all inherited members.

createBookmarks()ipe::PdfWriter
createPages()ipe::PdfWriter
createPageView(int page, int view)ipe::PdfWriter
createTrailer()ipe::PdfWriter
createXmlStream(String xmldata, bool preCompressed)ipe::PdfWriter
PdfWriter(TellStream &stream, const Document *doc, const FontPool *pool, bool markedView, int fromPage, int toPage, int compression)ipe::PdfWriter
~PdfWriter()ipe::PdfWriter

ipe-7.1.4/build/doc/ftv2link.png0000644000175000017500000000135212120621776016270 0ustar otfriedotfried‰PNG  IHDRÚ}\ˆ±IDATxíMOS[…Ÿžsúa?-XZ(PD4‚ AWbu`b 77wäHFÆCËÔÂÿà/`vo„ˆAPòq‹P @ ­ûÝè980 îà¤+»§Ýy×^ïZï9SW¹\83g‰3'°Nâçl¹¸_b¯p ïåûÆVÜÖ¡€Ÿ×"¬Ö†X€d]Ðà3“ÉÃÄÌ™xŸ ßMàœ[<çSPkvc—hÈ'…™˜^Åm™hØ7 `Û™¦ èÀåráq›‘œ¾!daeKŸþÆÕ˜:Ì*³_דâèi?I–eP*B7Ÿ¿åô!¹Ýgr6Ër6oKbëþãðôrI”ËTˆüªŒ¨xóö=›ù¢&‰(e+ßóÄkýÇ`ëÁÜb.“¸ÐW×w0¥°jÑzN™¬|©WEãµ¢a¯6[öX†AkÓù*/œ¨‰€ÉY­ ÿV’§–u²jÂ>1W *½·°PGŽzÿ¨/Eg{ ŸÇâaoŠÁVú:è¿™¤1$ôR§W,–ªà¨@ŠË56¾ÀÔÜ-¾,mê¸Î/æè¹– òr5¥T*S(Vf8ö9u’ Õ£w›ùóa=Í<{Ò¡UŒ÷r¯+ÉådDÏF$è°…£é¿`zþ»ÎúöN‘µÜ®0Q3£~_^Ëóâ¯N=ˆvpTà±LžT}ˆîkq†Òm<¼ÎÓ?Zh¿X£ï_þÝ¥[)ƒ `gêÃa_Ô*äÔ2`'=õ´Fÿ2EâÁPú ÷»›l=8‹Wv°%THqÉ¿<"¤ïG¾ÆxH{#ÆÖ«aÔJÕÞ‡—m‹„ çñKsÿàñVŠØ¡°·MâÒ^ TÁ– Ý›r¥ß½ømüÿ_™?ªWİ÷#uIEND®B`‚ipe-7.1.4/build/doc/manual_25.html0000644000175000017500000001055312120621776016477 0ustar otfriedotfried Ipe Manual -- 5.4 Interaction of the snapping modes
5.5 Examples5 Snapping5.3 Angular snapping5.4 Interaction of the snapping modes

5.4 Interaction of the snapping modes

Not all the snapping modes can be active at the same time, even if all buttons are pressed. Here we have a close look at the possible interactions, and the priorities of snapping.

The two angular snapping modes restrict the possible mouse positions to a one-dimensional subspace of the canvas. Therefore, they are incompatible with the modes that try to snap to a zero-dimensional subspace, namely vertex snapping, intersection snapping, and grid snapping. Consequently, when one of the angular snapping modes is on, vertex snapping, intersection snapping, and grid snapping are ineffective.

On the other hand, it is reasonable to snap to boundaries while in an angular snapping mode, and this function is actually implemented correctly. When both angular and boundary snapping are on, Ipe will compute intersections between the snap lines with the boundaries of your objects, and whenever the mouse position on the snap line comes close enough to an intersection, the mouse is snapped to that intersection.

The two angular snapping modes themselves can also coexist in the same fashion. If both angular and automatic angular snapping are enabled, Ipe computes the intersection point between the snap lines defined by the two origins and snaps there. It the snap lines are parallel or coincide, automatic angular snapping is used.

When no angular snapping mode is active, Ipe has three priorities. First, Ipe checks whether the closest vertex or intersection point is close enough. If that is not the case, the closest boundary edge is determined. If even that is too far away, Ipe uses grid snapping (assuming all these modes are enabled).

Note that this can actually mean that snapping is not to the closest point on an object. Especially for intersections of two straight edges, the closest point can never be the intersection point, as in the figure below!

ipe-7.1.4/build/doc/cpp-ipelets.html0000644000175000017500000004660112120621776017144 0ustar otfriedotfried Ipelib: Ipelets written in C++
Ipelets written in C++

As in Ipe 6, it is possible to write ipelets entirely in C++. Different from Ipe 6, however, the labels of the ipelet and its functions must now be specified in a short Lua wrapper with some boilerplate code. This Lua code will invoke your C++ methods.

C++ ipelet framework

The C++ code is in a dynamically loaded library (DLL), that you place on Ipe's C++ ipelet path. The DLL has to be written in C++, and must export a function newIpelet that creates an object derived from the class Ipelet (defined in ipelet.h). Here is a minimal ipelet implementation:

#include "ipelet.h"

class MyIpelet : public ipe::Ipelet {
public:
  virtual int ipelibVersion() const { return IPELIB_VERSION; }
  virtual bool run(int function, ipe::IpeletData *data, ipe::IpeletHelper *helper);
};

bool MyIpelet::run(int function, ipe::IpeletData *data, ipe::IpeletHelper *helper)
{
  // this is where you do all the work
}

IPELET_DECLARE ipe::Ipelet *newIpelet()
{
  return new MyIpelet;
}

When the ipelet is executed, Ipe hands it a structure with some information about the document, in particular a pointer to the current page. The ipelet can examine the selected objects, and modify the page in any way it wishes. (It is not possible to modify the document outside the current page, as this would interfere with the undo stack). It can also request services from the Ipe application through the IpeletHelper object, for instance to display a message in the status bar, to pop up message boxes and to obtain input from the user.

The run method must return true if it modified the document page. This is used to create an item on the undo stack so that this change can be undone. If the run method returns false, then no undo stack item is created. In this case, the ipelet must not modify the page.

The Lua wrapper

You need to provide a small Lua wrapper that declares the names of the ipelet and its methods, and that calls your C++ code when an ipelet method is invoked. This wrapper will look as follows:

-- Lua wrapper for C++ ipelet "myipelet"

label = "My Ipelet"

about = "This ipelet is for explanation only"

-- this variable will store the C++ ipelet when it has been loaded
ipelet = false

function run(ui, num)
  if not ipelet then ipelet = assert(loadIpelet("myipelet"))
  ui:runIpelet(ipelet, mum) 
end

methods = { { label = "First function of my ipelet" },
            { label = "Second function of my ipelet" }
          }

If the ipelet contains only a single method, then the methods table is omitted.

The Lua wrapper needs to be placed in Ipe's ipelet directory. When Ipe starts up, it automatically loads all ipelets from this directory. Note that the wrapper above does not immediately load the C++ ipelet (using loadIpelet) when the Lua wrapper is loaded by Ipe, but only when the first method of the ipelet is called. This is considered good style.

An example ipelet

Kgon is a minimal ipelet that you can use as the basis for your own development. It defines only a single function, and makes no use of the function argument to run.

// --------------------------------------------------------------------
// Ipelet for creating regular k-gons
// --------------------------------------------------------------------
#include "ipelet.h"
#include "ipepath.h"
#include "ipepage.h"
using namespace ipe;
// --------------------------------------------------------------------
class KGonIpelet : public Ipelet {
public:
virtual int ipelibVersion() const { return IPELIB_VERSION; }
virtual bool run(int, IpeletData *data, IpeletHelper *helper);
};
// --------------------------------------------------------------------
bool KGonIpelet::run(int, IpeletData *data, IpeletHelper *helper)
{
Page *page = data->iPage;
int sel = page->primarySelection();
if (sel < 0) {
helper->message("No selection");
return false;
}
const Path *p = page->object(sel)->asPath();
if (p == 0 || p->shape().countSubPaths() != 1 ||
helper->message("Primary selection is not a circle");
return false;
}
String str;
if (!helper->getString("Enter k (number of corners)", str))
return false;
int k = Lex(str).getInt();
if (k < 3 || k > 1000)
return false;
const Ellipse *e = p->shape().subPath(0)->asEllipse();
Matrix m = p->matrix() * e->matrix();
Vector center = m.translation();
Vector v = m * Vector(1,0);
double radius = (v - center).len();
Curve *sp = new Curve;
double alpha = 2.0 * IpePi / k;
Vector v0 = center + radius * Vector(1,0);
for (int i = 1; i < k; ++i) {
Vector v1 = center + radius * Vector(Angle(i * alpha));
sp->appendSegment(v0, v1);
v0 = v1;
}
sp->setClosed(true);
Shape shape;
shape.appendSubPath(sp);
Path *obj = new Path(data->iAttributes, shape);
page->append(ESecondarySelected, data->iLayer, obj);
helper->message("Created regular k-gon");
return true;
}
// --------------------------------------------------------------------
IPELET_DECLARE Ipelet *newIpelet()
{
return new KGonIpelet;
}
// --------------------------------------------------------------------

The Lua wrapper would look like this:

----------------------------------------------------------------------
-- kgon ipelet description
----------------------------------------------------------------------
label = "Regular k-gon"
about = [[
Constructs a regular k-gon from a circle.
This ipelet is part of Ipe.
]]
-- this variable will store the C++ ipelet when it has been loaded
ipelet = false
function run(model)
if not ipelet then ipelet = assert(ipe.Ipelet(dllname)) end
model:runIpelet(label, ipelet)
end
-- define a shortcut for this function
shortcuts.ipelet_1_kgon = "Alt+Ctrl+K"
----------------------------------------------------------------------

Compiling ipelets on Unix

The ipelet must be compiled as a shared library and must be linked with the Ipe library ``libipe.so''. C++ mandates that it must be compiled with the same compiler that was used to compile Ipe. Have a look at the ipelet sources in the Ipe source distribution, and their makefiles for details on compiling them.

Compiling ipelets on Windows

The ipelet must be compiled as a DLL and must be linked with the Ipe library ``ipe.dll''. C++ mandates that it must be compiled with the same compiler that was used to compile Ipe. If you use the binary Ipe distribution for Windows, that means you have to use the MinGW compiler. (If you haven't used it before: MinGW is a port of g++ for Windows).

The Ipe Windows distribution contains the necessary header files and the library to compile ipelets, as well as the source of the kgon'' andgoodies'' ipelets as examples. To compile the ``kgon'' example, open a command shell, make sure MinGW g++ is on your path, and say:

  g++ -c -O2 -DWIN32 -fno-exceptions -fno-rtti -Iinclude kgon.cpp
  g++ -Wl,-enable-stdcall-fixup -Wl,-enable-auto-import \
  -Wl,-enable-runtime-pseudo-reloc -Wl,-s -shared -o kgon.dll kgon.o \
  -Llib -lipe

Place the resulting kgon.dll in the ipelets subdirectory, and restart Ipe.


ipe-7.1.4/build/doc/intersection.svg0000644000175000017500000005266312120621776017265 0ustar otfriedotfried ipe-7.1.4/build/doc/structipe_1_1_font.html0000644000175000017500000003454612120621776020434 0ustar otfriedotfried Ipelib: ipe::Font Struct Reference

#include <ipefontpool.h>

Public Types

enum  TType { EType1, ETrueType }

Public Attributes

TType iType
String iName
int iLatexNumber
String iFontDict
String iFontDescriptor
String iStreamDict
int iLength1
int iLength2
int iLength3
Buffer iStreamData
bool iHasEncoding
String iEncoding [0x100]
bool iStandardFont
int iWidth [0x100]

Related Functions

(Note that these are not member functions.)

typedef std::vector< FontFontPool

Detailed Description

A text font.

Member Enumeration Documentation

Ipe supports two types of fonts.

Enumerator:
EType1 
ETrueType 

Friends And Related Function Documentation

typedef std::vector<Font> FontPool
related

A list of fonts used by a Document.

Member Data Documentation

TType ipe::Font::iType

The font type.

String ipe::Font::iName

The name of this font (e.g. "Times-Roman").

int ipe::Font::iLatexNumber

The font id in the Pdflatex output: /Fxx.

String ipe::Font::iFontDict

The font dictionary in the PDF file.

String ipe::Font::iFontDescriptor

The font descriptor in the PDF file.

String ipe::Font::iStreamDict

The stream dictionary for the font stream in the PDF file.

int ipe::Font::iLength1

The values of LengthX in the font stream in the PDF file.

int ipe::Font::iLength2
int ipe::Font::iLength3
Buffer ipe::Font::iStreamData

The stream data for the font stream in the PDF file.

bool ipe::Font::iHasEncoding

Is there an explicit encoding for this font?

String ipe::Font::iEncoding[0x100]

The encoding of this font.

bool ipe::Font::iStandardFont

Is this one of the 14 standard fonts?

int ipe::Font::iWidth[0x100]

The width of each character in font units.


The documentation for this struct was generated from the following file:
  • ipefontpool.h

ipe-7.1.4/build/doc/ftv2plastnode.png0000644000175000017500000000034512120621776017325 0ustar otfriedotfried‰PNG  IHDRɪ|¬IDATxí=QF‘Ø¥D«ÔkÄ:‰F©PK؃=V@§Õ³ Õ8SHxñÌ0bnrróŠ{ò½¿¾’$ ÀÏTŠP  ö¼X¬OÛd6êìòð"°²S´±O¥B€(¡àQé)š+YĈ ÒªËRÉÐ>VtÉsˆm9(ê„䜥k‚-@ȧ-Ü$ó b Ò[he ¿Kp-ôl|CùÿApRG'rÍ­aIEND®B`‚ipe-7.1.4/build/doc/classipe_1_1_data_source-members.html0000644000175000017500000000540712120621776023162 0ustar otfriedotfried Ipelib: Member List
ipe::DataSource Member List

This is the complete list of members for ipe::DataSource, including all inherited members.

getChar()=0ipe::DataSourcepure virtual
~DataSource()=0ipe::DataSourcepure virtual

ipe-7.1.4/build/doc/classipe_1_1_all_attributes-members.html0000644000175000017500000002231712120621776023706 0ustar otfriedotfried Ipelib: Member List
ipe::AllAttributes Member List

ipe-7.1.4/build/doc/ftv2folderopen.png0000644000175000017500000000112512120621776017466 0ustar otfriedotfried‰PNG  IHDRÚ}\ˆIDATxí]?oÓPÿ9iš4i°;ii“¶‰ZЉ‘‰ÀÀ7`bèÔÙ¬Øù,HìU'ô$*Tµ]‚T¡DPÚÄ6wÏ}‰;¡C; a¿ÓߟûÝïîž¼jAÀ­InSþ}€9H“ÓŽ|?íÁ÷ =_ÊÆŠ­†¥Àue*;¯YEäsYäæB¢Ÿ¿þÄ—£sÙ½½ÙŒ† É«›©ÀYÇq !GÇ¿v̇¹ÑØ®š °Œ‚ÔF¹}q¥b]÷7í·0)Úd›¾ÿð-èº}Pfä£ÖY{4™ÑÂ@}úæôñ2ÛüÔ—ñúåNŒI‚ÁǃcçÁº%£¬UаI³mc±ô˜å¼ÔÆüÈ>é¸xþt9Æ$µý OæVE*õU´Ì‚ç#ž×ˆ•ïûr@l$øPÿrHaaÇ¥ ²›dZ®rè‘ãqI„o¼øT\Ž,tªj2FAxv-LŸp׌p TÄI/ \¥sfí½; jViTƒèú¤o^cpÅü¼ûû»Ïb]”€¢¤<†aþÕœ²“ßÓ˜y“£§9:Œîù+À³€ñà,E žf³6éNˆÄE£KU}Ü^;¶ØnZ¢uß­US4— ѬëbížN¶.Úk¦ØjTÄöº%µªâ i¯VÄÊÝò§™ Èù¸)ùÿG€™òºJ@T x”IEND®B`‚ipe-7.1.4/build/doc/functions_0x6c.html0000644000175000017500000002012412120621776017557 0ustar otfriedotfried Ipelib: Class Members
Here is a list of all class members with links to the classes they belong to:

- l -


ipe-7.1.4/build/doc/lua.html0000644000175000017500000001036012120621776015471 0ustar otfriedotfried Ipelib: Programming in Lua
Programming in Lua

The library libipelua implements Lua bindings for many classes in Ipelib. The bindings are available in Lua ipelets, as well as in Lua scripts executed using the ipescript program.

These pages document the Lua bindings to Ipelib:

When writing Ipelets in Lua, you have access to additional methods provided by the Ipe program itself:

Examples

Here is a Lua script that reads an Ipe document and then recenters each page on the paper. You can run this script as "ipescript recenter".

-- recenter.lua
-- center objects on each page of the document

if #argv ~= 2 then
  io.stderr:write("Usage: ipescript recenter <inputfile> <outputfile>\n")
  return
end

inname = argv[1]
outname = argv[2]

doc = assert(ipe.Document(inname))

-- make sure we have size information for text
assert(doc:runLatex())

layout = doc:sheets():find("layout")
fs = layout.framesize

for i,p in doc:pages() do
  box = ipe.Rect()
  for j = 1,#p do
    box:add(p:bbox(j))
  end
  nx = (fs.x - box:width()) / 2
  ny = (fs.y - box:height()) / 2
  trans = ipe.Vector(nx, ny) - box:bottomLeft()
  m = ipe.Translation(trans)
  for j = 1,#p do
    p:transform(j, m)
  end
end
doc:save(outname)

Here is a small Lua script that takes an Ipe document and exports each view separately in EPS format:

-- splitviews.lua
-- export each view of an Ipe document separately

if #argv ~= 1 then
  io.stderr:write("Usage: ipescript splitviews <file>\n")
  return
end
fname = argv[1]

i = fname:find("%.[^.]+$")
if i then
  epsname = fname:sub(1,i-1)
else
  epsname = fname
end

doc = assert(ipe.Document(fname))

-- need latex information to save as Postscript
assert(doc:runLatex())

for i,p in doc:pages() do
  io.stderr:write("Saving page " .. i .. "\n") 
  for j = 1, p:countViews() do
    out = epsname .. "-" .. i .. "-" .. j .. ".eps"
    io.stderr:write("Saving view " .. i .. "-" .. j .. " as " .. out .. "\n") 
    doc:exportView(out, "eps", nil, i, j)
  end
end

For more examples, have a look at the scripts in your Ipe installation, such as add-style.lua or update-styles.lua.


ipe-7.1.4/build/doc/classipe_1_1_visitor-members.html0000644000175000017500000000762012120621776022367 0ustar otfriedotfried Ipelib: Member List
ipe::Visitor Member List

This is the complete list of members for ipe::Visitor, including all inherited members.

visitGroup(const Group *obj)ipe::Visitorvirtual
visitImage(const Image *obj)ipe::Visitorvirtual
visitPath(const Path *obj)ipe::Visitorvirtual
visitReference(const Reference *obj)ipe::Visitorvirtual
visitText(const Text *obj)ipe::Visitorvirtual
~Visitor()ipe::Visitorvirtual

ipe-7.1.4/build/doc/classipe_1_1_style_sheet.html0000644000175000017500000013113112120621776021563 0ustar otfriedotfried Ipelib: ipe::StyleSheet Class Reference

#include <ipestyle.h>

Classes

struct  PageNumberStyle
 How to show page numbers on the paper. More...
struct  TitleStyle
 Style of the title on a page. More...

Public Member Functions

 StyleSheet ()
void addSymbol (Attribute name, const Symbol &symbol)
const SymbolfindSymbol (Attribute sym) const
void addGradient (Attribute name, const Gradient &s)
const GradientfindGradient (Attribute sym) const
void addTiling (Attribute name, const Tiling &s)
const TilingfindTiling (Attribute sym) const
void addEffect (Attribute name, const Effect &e)
const EffectfindEffect (Attribute sym) const
void add (Kind kind, Attribute name, Attribute value)
bool has (Kind kind, Attribute sym) const
Attribute find (Kind, Attribute sym) const
void saveAsXml (Stream &stream, bool saveBitmaps=false) const
void allNames (Kind kind, AttributeSeq &seq) const
bool isStandard () const
String preamble () const
void setPreamble (const String &str)
String encoding () const
void setEncoding (const String &enc)
const Layoutlayout () const
void setLayout (const Layout &margins)
const TextPaddingtextPadding () const
void setTextPadding (const TextPadding &pad)
const TitleStyletitleStyle () const
void setTitleStyle (const TitleStyle &ts)
const PageNumberStylepageNumberStyle ()
void setPageNumberStyle (const PageNumberStyle &pns)
void addCMap (String s)
void allCMaps (std::vector< String > &seq) const
void setLineCap (TLineCap s)
void setLineJoin (TLineJoin s)
void setFillRule (TFillRule s)
TLineCap lineCap () const
TLineJoin lineJoin () const
TFillRule fillRule () const
String name () const
void setName (const String &name)

Static Public Member Functions

static StyleSheetstandard ()

Detailed Description

A style sheet maps symbolic names to absolute values.

Ipe documents can use symbolic attributes, such as 'normal', 'fat', or 'thin' for line thickness, or 'red', 'navy', 'turquoise' for color. The mapping to an absolute pen thickness or RGB value is performed by a StyleSheet.

Style sheets are always included when the document is saved, so that an Ipe document is self-contained.

The built-in standard style sheet is minimal, and only needed to provide sane fallbacks for all the "normal" settings.

Constructor & Destructor Documentation

StyleSheet::StyleSheet ( )

The default constructor creates an empty style sheet.

Member Function Documentation

StyleSheet * StyleSheet::standard ( )
static

Create standard built-in style sheet.

void StyleSheet::addSymbol ( Attribute  name,
const Symbol symbol 
)

Add a symbol object.

const Symbol * StyleSheet::findSymbol ( Attribute  attr) const

Find a symbol object with given name.

If attr is not symbolic or if the symbol doesn't exist, returns 0.

void StyleSheet::addGradient ( Attribute  name,
const Gradient s 
)

Add gradient to this style sheet.

const Gradient * StyleSheet::findGradient ( Attribute  sym) const

Find gradient in style sheet cascade.

void StyleSheet::addTiling ( Attribute  name,
const Tiling s 
)

Add tiling to this style sheet.

const Tiling * StyleSheet::findTiling ( Attribute  sym) const

Find tiling in style sheet cascade.

void StyleSheet::addEffect ( Attribute  name,
const Effect e 
)
const Effect * StyleSheet::findEffect ( Attribute  sym) const
void StyleSheet::add ( Kind  kind,
Attribute  name,
Attribute  value 
)

Add an attribute.

Does nothing if name is not symbolic.

bool StyleSheet::has ( Kind  kind,
Attribute  sym 
) const

Check whether symbolic attribute is defined.

This method also works for ESymbol, EGradient, ETiling, and EEffect.

Returns true if sym is not symbolic.

Attribute StyleSheet::find ( Kind  kind,
Attribute  sym 
) const

Find a symbolic attribute.

If sym is not symbolic, returns sym itself. If sym cannot be found, returns the "undefined" attribute. In all other cases, the returned attribute is guaranteed to be absolute.

void StyleSheet::saveAsXml ( Stream stream,
bool  saveBitmaps = false 
) const

Save style sheet in XML format.

void StyleSheet::allNames ( Kind  kind,
AttributeSeq seq 
) const

Return all symbolic names in the style sheet cascade.

Names are simply appended from top to bottom of the cascade. Names are inserted only once.

bool ipe::StyleSheet::isStandard ( ) const
inline

Return whether this is the standard style sheet built into Ipe.

String ipe::StyleSheet::preamble ( ) const
inline

Return Latex preamble.

void ipe::StyleSheet::setPreamble ( const String str)
inline

Set LaTeX preamble.

String ipe::StyleSheet::encoding ( ) const
inline

Return Latex encoding.

void ipe::StyleSheet::setEncoding ( const String enc)
inline

Set Latex encoding.

const Layout * StyleSheet::layout ( ) const

Return page layout (or 0 if none defined).

void StyleSheet::setLayout ( const Layout margins)

Set page layout.

const TextPadding * StyleSheet::textPadding ( ) const

Return text object padding (for bbox computation).

void StyleSheet::setTextPadding ( const TextPadding pad)

Set padding for text object bbox computation.

const StyleSheet::TitleStyle * StyleSheet::titleStyle ( ) const

Return title style (or 0 if none defined).

void StyleSheet::setTitleStyle ( const TitleStyle ts)

Set style of page titles.

const StyleSheet::PageNumberStyle * StyleSheet::pageNumberStyle ( )

Return page number style.

void StyleSheet::setPageNumberStyle ( const PageNumberStyle pns)

Set style of page numbering.

void StyleSheet::addCMap ( String  s)

Add font s to list of fonts with cmap generation.

void StyleSheet::allCMaps ( std::vector< String > &  seq) const
void StyleSheet::setLineCap ( TLineCap  s)

Set line cap.

void StyleSheet::setLineJoin ( TLineJoin  s)

Set line join.

void StyleSheet::setFillRule ( TFillRule  s)

Set fill rule.

TLineCap ipe::StyleSheet::lineCap ( ) const
inline

Return line cap.

TLineJoin ipe::StyleSheet::lineJoin ( ) const
inline

Return line join.

TFillRule ipe::StyleSheet::fillRule ( ) const
inline

Return path fill rule.

String ipe::StyleSheet::name ( ) const
inline

Return name of style sheet.

void ipe::StyleSheet::setName ( const String name)
inline

Set name of style sheet.


The documentation for this class was generated from the following files:
  • ipestyle.h
  • ipestdstyles.cpp
  • ipestyle.cpp

ipe-7.1.4/build/doc/functions_0x68.html0000644000175000017500000001402712120621776017511 0ustar otfriedotfried Ipelib: Class Members
Here is a list of all class members with links to the classes they belong to:

- h -


ipe-7.1.4/build/doc/classipe_1_1_reference-members.html0000644000175000017500000004770612120621776022637 0ustar otfriedotfried Ipelib: Member List
ipe::Reference Member List

This is the complete list of members for ipe::Reference, including all inherited members.

accept(Visitor &visitor) const ipe::Referencevirtual
addToBBox(Rect &box, const Matrix &m, bool cp) const ipe::Referencevirtual
asGroup()ipe::Objectvirtual
asImage()ipe::Objectvirtual
asPath()ipe::Objectvirtual
asReference()ipe::Referencevirtual
asText()ipe::Objectvirtual
checkStyle(const Cascade *sheet, AttributeSeq &seq) const ipe::Referencevirtual
checkSymbol(Kind kind, Attribute attr, const Cascade *sheet, AttributeSeq &seq)ipe::Objectprotectedstatic
clone() const ipe::Referencevirtual
distance(const Vector &v, const Matrix &m, double bound) const ipe::Referencevirtual
draw(Painter &painter) const ipe::Referencevirtual
drawSimple(Painter &painter) const ipe::Referencevirtual
EGroup enum valueipe::Object
EHasFill enum valueipe::Reference
EHasPen enum valueipe::Reference
EHasSize enum valueipe::Reference
EHasStroke enum valueipe::Reference
EImage enum valueipe::Object
EIsArrow enum valueipe::Reference
EIsMark enum valueipe::Reference
EPath enum valueipe::Object
EReference enum valueipe::Object
EText enum valueipe::Object
fill() const ipe::Referenceinline
flags() const ipe::Referenceinline
flagsFromName(String name)ipe::Referencestatic
getAttribute(Property prop)ipe::Referencevirtual
iMatrixipe::Objectprotected
iPinnedipe::Objectprotected
iTransformationsipe::Objectprotected
matrix() const ipe::Objectinline
name() const ipe::Referenceinline
Object()ipe::Objectexplicitprotected
Object(const AllAttributes &attr)ipe::Objectexplicitprotected
Object(const Object &rhs)ipe::Objectprotected
Object(const XmlAttributes &attr)ipe::Objectexplicitprotected
pen() const ipe::Referenceinline
pinned() const ipe::Objectvirtual
position() const ipe::Referenceinline
Reference(const AllAttributes &attr, Attribute name, Vector pos)ipe::Referenceexplicit
Reference(const XmlAttributes &attr, String data)ipe::Referenceexplicit
saveAsXml(Stream &stream, String layer) const ipe::Referencevirtual
saveAttributesAsXml(Stream &stream, String layer) const ipe::Objectprotected
setAttribute(Property prop, Attribute value, Attribute stroke, Attribute fill)ipe::Referencevirtual
setFill(Attribute color)ipe::Reference
setMatrix(const Matrix &matrix)ipe::Object
setName(Attribute name)ipe::Reference
setPen(Attribute pen)ipe::Reference
setPinned(TPinned pin)ipe::Object
setSize(Attribute size)ipe::Reference
setStroke(Attribute color)ipe::Reference
setTransformations(TTransformations trans)ipe::Object
size() const ipe::Referenceinline
snapBnd(const Vector &mouse, const Matrix &m, Vector &pos, double &bound) const ipe::Referencevirtual
snapVtx(const Vector &mouse, const Matrix &m, Vector &pos, double &bound) const ipe::Referencevirtual
stroke() const ipe::Referenceinline
transformations() const ipe::Objectinline
type() const ipe::Referencevirtual
Type enum nameipe::Object
~Object()=0ipe::Objectpure virtual

ipe-7.1.4/build/doc/classipe_1_1_thumbnail-members.html0000644000175000017500000000636712120621776022662 0ustar otfriedotfried Ipelib: Member List
ipe::Thumbnail Member List

This is the complete list of members for ipe::Thumbnail, including all inherited members.

height() const ipe::Thumbnailinline
render(const Page *page, int view)ipe::Thumbnail
Thumbnail(const Document *doc, int width)ipe::Thumbnail
~Thumbnail()ipe::Thumbnail

ipe-7.1.4/build/doc/luaipeui.html0000644000175000017500000001677512120621776016545 0ustar otfriedotfried Ipelib: Lua bindings for dialogs and menus
Lua bindings for dialogs and menus

The ipeui module provides dialogs and popup menus for Lua. It does not depend on any other Ipe component, and can be reused in other Lua projects.

Global methods

There are a few global methods in the ipeui module:

ipeui.closeAllWindows()   -- sends all windows a close event (not on Win32)
ipeui.startBrowser(url)   -- on Win32 only
ipeui.setClipboard(text)  -- store text on system clipboard
text = ipeui.clipboard()  -- get text property from system clipboard
dt = ipeui.currentDateTime() -- returns string with current date and time

Predefined dialogs

The following are predefined dialogs. In all cases, parent can either be nil or a Window ID.

-- get a filename from user
-- type is "open" or "save"
-- filter e.g. "XML (*.xml);;PDF (*.pdf)"
-- dir is nil or a starting directory
-- selected is nil or the filter originally selected
-- returns nil if the dialog is canceled
-- or filename and selected filter
ipeui.fileDialog(parent, type, caption, filter, dir, selected)

-- choose a color
-- r,g,b are in the range 0.0 to 1.0
-- returns nil or a (r,g,b) triple
ipeui.getColor(parent, title, r, g, b)

-- show a message box
-- type is one of "none" "warning" "information" "question" "critical"
-- details may be nil
-- buttons may be nil (for "ok") or one of 
-- "ok" "okcancel" "yesnocancel", "discardcancel", "savediscardcancel", 
-- return 1 for ok/yes/save, 0 for no/discard, -1 for cancel
ipeui.messageBox(parent, type, text, details, buttons)

-- this dialog only returns when the external editor has finished
ipeui.WaitDialog(parent, command)

Dialogs

Other dialogs can be constructed programmatically. A dialog consists of various elements layed out in a grid, and a row of buttons underneath. Create the dialog by adding elements using 'add', and filling the button row using 'addButton'. The 'action' for 'addButton' can be one of the strings "accept" or "reject", or a Lua method.

d = ipeui.Dialog(parent, window_title)

d:add(name, what, options, row, column, row_span, column_span)
d:addButton(name, caption, action)

d:setStretch("row", row_number, stretch_factor)
d:setStretch("column", row_number, stretch_factor)

d:set(name, value)
value = d:get(name)

-- set whether escape should be ignored (true/false)
d:set("ignore-escape", flag)

-- returns true if dialog was accepted
d:execute()
d:execute(size)   -- where size == { width, height }

name can be an arbitrary string. what must be one of

button, text, list, label, combo, checkbox, input

options is a table. Most fields are optional:

-- button:
label="string"  (Required!)
action="accept" or "reject" or a Lua method

-- label:
label="string"  (Required!)

-- text:
read_only=bool
syntax="logfile" or "xml" or "latex"

-- list and combo:
array of list items (strings)

-- checkbox:
label="string"  (Required!)
action= Lua method  (called when state changed)

-- input:

The argument of set is:

  • a string value for label, text, and input,
  • a either an integer or an array of string items for list and combo,
  • a boolean for checkbox.

The result value of get is:

  • a string for text and input,
  • an integer for list (or nil if there is no current item) or combo,
  • a boolean for checkbox.

Popup menus

Popup menus are constructed and shown as follows:

m = ipeui.Menu(parent)  
item, no, subitem = m:execute(global_position)

When the menu is cancelled, execute returns nil.

You can then add items to the menu one by one. A simple item is added like this:

m:add("name", "Label")

When this item is selected, execute returns name, 0, and an empty string.

The following line adds an entire submenu:

m:add("name", "Submenu", { "alpha", "beta", "gamma" } )

When an item from this submenu is selected, execute returns name, the index into the submenu, and the name of the submenu item.

When the strings in the table are not directly the visible labels for the submenu, a Lua function can be used to convert them:

m:add("name", "Submenu", { "alpha", "beta", "gamma" },
      function (i, item) return "select " .. item end )

The final argument can either be a string or a function. If it is a string, then all items are checkable, and the item whose name is identical to the final argument is checked. Otherwise, the function maps item number and name to a color (three numbers in the range 0.0 to 1.0). This is then used to display a color icon.

Timers

Timers are constructed as follows:

t = ipeui.Timer(table, "method")

When the timer times out, it will call the method named method in the Lua table table. The timer stores only a weak reference to the table, so the timer will not stop the table from being garbage collected.

The timer is controlled using the methods:

timer:setInterval(interval)     -- an integer in milliseconds
timer:setSingleShot(bool)       -- default is repeating timer
timer:start()   
timer:stop()
a = timer:active()              -- true if the timer is running

ipe-7.1.4/build/doc/classipe_1_1_base64_source-members.html0000644000175000017500000000606712120621776023340 0ustar otfriedotfried Ipelib: Member List
ipe::Base64Source Member List

This is the complete list of members for ipe::Base64Source, including all inherited members.

Base64Source(DataSource &source)ipe::Base64Source
getChar()ipe::Base64Sourcevirtual
~DataSource()=0ipe::DataSourcepure virtual

ipe-7.1.4/build/doc/manual_37.html0000644000175000017500000000642212120621776016502 0ustar otfriedotfried Ipe Manual -- 8.3 Troubleshooting the LaTeX-conversion
8.4 Using Truetype fonts8 Advanced topics8.2 Writing ipelets8.3 Troubleshooting the LaTeX-conversion

8.3 Troubleshooting the LaTeX-conversion

Ipe converts text objects from their Latex source representation to a representation that can be rendered and included in Postscript and PDF by creating a Latex source file and running Pdflatex. This happens in a dedicated directory, which Ipe creates the first time it is used. The Latex source and output files are left in that directory and not deleted even when you close Ipe, to make it easy to solve problems with the Latex conversion process.

You can determine the directory used by Ipe using Show configuration in the Help menu. If you'd prefer to use a different directory, set the environment variable IPELATEXDIR before starting Ipe.

If Ipe fails to translate your text objects, and you cannot find the problem by looking at the log file displayed by Ipe (or Ipe doesn't even display the log file), you can terminate Ipe, go to the conversion directory, and run Pdflatex manually:

pdflatex ipetemp.tex
ipe-7.1.4/build/doc/group__attr.html0000644000175000017500000012730512120621776017245 0ustar otfriedotfried Ipelib: Ipe Attributes
Ipe Attributes

Classes

struct  ipe::Tiling
 A tiling pattern. More...
struct  ipe::Gradient
 A gradient pattern. More...
struct  ipe::Layout
 Layout of a Page. More...
struct  ipe::TextPadding
 Padding for text bounding box. More...
class  ipe::Color
 An absolute RGB color. More...
class  ipe::Effect
 Effect that Acrobat Reader will show on page change. More...
class  ipe::Repository
 Repository of strings. More...
class  ipe::Attribute
 An attribute of an Ipe Object. More...
class  ipe::AllAttributes
 Collection of all object attributes. More...
class  ipe::Symbol
 A symbol is a named object defined in an ipe::StyleSheet. More...

Typedefs

typedef std::vector< Attribute > ipe::AttributeSeq

Enumerations

enum  ipe::Kind {
  ipe::EPen = 0, ipe::ESymbolSize, ipe::EArrowSize, ipe::EColor,
  ipe::EDashStyle, ipe::ETextSize, ipe::ETextStretch, ipe::ETextStyle,
  ipe::EGridSize, ipe::EAngleSize, ipe::EOpacity, ipe::ETiling,
  ipe::ESymbol, ipe::EGradient, ipe::EEffect
}
enum  ipe::Property {
  ipe::EPropPen = 0, ipe::EPropSymbolSize, ipe::EPropFArrow, ipe::EPropRArrow,
  ipe::EPropFArrowSize, ipe::EPropRArrowSize, ipe::EPropFArrowShape, ipe::EPropRArrowShape,
  ipe::EPropStrokeColor, ipe::EPropFillColor, ipe::EPropMarkShape, ipe::EPropPathMode,
  ipe::EPropDashStyle, ipe::EPropTextSize, ipe::EPropTextStyle, ipe::EPropOpacity,
  ipe::EPropTiling, ipe::EPropGradient, ipe::EPropHorizontalAlignment, ipe::EPropVerticalAlignment,
  ipe::EPropLineJoin, ipe::EPropLineCap, ipe::EPropFillRule, ipe::EPropPinned,
  ipe::EPropTransformations, ipe::EPropTransformableText, ipe::EPropMinipage, ipe::EPropWidth
}
enum  ipe::TPathMode { ipe::EStrokedOnly, ipe::EStrokedAndFilled, ipe::EFilledOnly }
enum  ipe::THorizontalAlignment { ipe::EAlignLeft, ipe::EAlignRight, ipe::EAlignHCenter }
enum  ipe::TVerticalAlignment { ipe::EAlignBottom, ipe::EAlignBaseline, ipe::EAlignTop, ipe::EAlignVCenter }
enum  ipe::TLineJoin { ipe::EDefaultJoin, ipe::EMiterJoin, ipe::ERoundJoin, ipe::EBevelJoin }
enum  ipe::TLineCap { ipe::EDefaultCap, ipe::EButtCap, ipe::ERoundCap, ipe::ESquareCap }
enum  ipe::TFillRule { ipe::EDefaultRule, ipe::EWindRule, ipe::EEvenOddRule }
enum  ipe::TPinned { ipe::ENoPin = 0x00, ipe::EHorizontalPin = 0x01, ipe::EVerticalPin = 0x02, ipe::EFixedPin = 0x03 }
enum  ipe::TTransformations { ipe::ETransformationsTranslations, ipe::ETransformationsRigidMotions, ipe::ETransformationsAffine }
enum  ipe::TSelect { ipe::ENotSelected = 0, ipe::EPrimarySelected, ipe::ESecondarySelected }

Variables

const char *const ipe::kind_names []
const char *const ipe::property_names []

Detailed Description

Attributes for Ipe objects.

Ipe objects have attributes such as color, line width, dash pattern, etc. Most attributes can be symbolic (the need to be looked up in a style sheet before rendering) or absolute.

The Color class represents absolute values of colors. The class Attribute encapsulates all attributes that can be either symbolic or absolute.

The Lua bindings for attributes are described here.

Typedef Documentation

A sequence of attribute values.

Enumeration Type Documentation

enum ipe::Kind

The different kinds of attributes.The same symbolic attribute (say "normal") has a different value in the StyleSheet depending on the Kind of attribute. The main use for Kind is as an argument to StyleSheet::find.

ESymbol, EGradient, ETiling, and EEffect have their own lookup methods in the StyleSheet. The values are still useful as an argument to allNames(), has(), and findDefinition().

Enumerator:
EPen 
ESymbolSize 
EArrowSize 
EColor 
EDashStyle 
ETextSize 
ETextStretch 
ETextStyle 
EGridSize 
EAngleSize 
EOpacity 
ETiling 
ESymbol 
EGradient 
EEffect 

A Property identifies an attribute that an object can have.The Property identifies a unique attribute of an object, while different Property values can be of the same ipe::Kind. For instance, both EPropStrokeColor and EPropFillColor identify an Attribute of Kind EColor.

Enumerator:
EPropPen 
EPropSymbolSize 
EPropFArrow 
EPropRArrow 
EPropFArrowSize 
EPropRArrowSize 
EPropFArrowShape 
EPropRArrowShape 
EPropStrokeColor 
EPropFillColor 
EPropMarkShape 
EPropPathMode 
EPropDashStyle 
EPropTextSize 
EPropTextStyle 
EPropOpacity 
EPropTiling 
EPropGradient 
EPropHorizontalAlignment 
EPropVerticalAlignment 
EPropLineJoin 
EPropLineCap 
EPropFillRule 
EPropPinned 
EPropTransformations 
EPropTransformableText 
EPropMinipage 
EPropWidth 

Path mode (stroked, filled, or both).

Enumerator:
EStrokedOnly 
EStrokedAndFilled 
EFilledOnly 

Horizontal alignment.

Enumerator:
EAlignLeft 
EAlignRight 
EAlignHCenter 

Vertical alignment.

Enumerator:
EAlignBottom 
EAlignBaseline 
EAlignTop 
EAlignVCenter 

Line join style.

The EDefaultJoin means to use the setting from the style sheet.

Enumerator:
EDefaultJoin 
EMiterJoin 
ERoundJoin 
EBevelJoin 

Line cap style.

The EDefaultCap means to use the setting from the style sheet.

Enumerator:
EDefaultCap 
EButtCap 
ERoundCap 
ESquareCap 

Fill rule.

The EDefaultRule means to use the setting from the style sheet.

Enumerator:
EDefaultRule 
EWindRule 
EEvenOddRule 

Pinning status of objects.

Enumerator:
ENoPin 
EHorizontalPin 
EVerticalPin 
EFixedPin 

Transformations that are permitted for an object.

Enumerator:
ETransformationsTranslations 
ETransformationsRigidMotions 
ETransformationsAffine 

Selection status of an object on the page.

Enumerator:
ENotSelected 
EPrimarySelected 
ESecondarySelected 

Variable Documentation

const char *const ipe::kind_names
Initial value:
{
"pen", "symbolsize", "arrowsize", "color",
"dashstyle", "textsize", "textstretch", "textstyle",
"gridsize", "anglesize", "opacity", "tiling",
"symbol", "gradient", "effect", 0 }
const char *const ipe::property_names
Initial value:
{
"pen", "symbolsize",
"farrow", "rarrow",
"farrowsize", "rarrowsize",
"farrowshape", "rarrowshape",
"stroke", "fill", "markshape",
"pathmode", "dashstyle",
"textsize", "textstyle",
"opacity", "tiling", "gradient",
"horizontalalignment", "verticalalignment",
"linejoin", "linecap", "fillrule",
"pinned", "transformations", "transformabletext",
"minipage", "width", 0 }

ipe-7.1.4/build/doc/group__canvas.html0000644000175000017500000000764112120621776017546 0ustar otfriedotfried Ipelib: Ipe canvas
Ipe canvas

Classes

class  ipe::Canvas
 A widget (control) that displays an Ipe document page. More...
class  ipe::Tool
 Abstract base class for various canvas tools. More...
class  ipe::PanTool
 A tool for panning the canvas. More...
class  ipe::SelectTool
 A tool for selecting objects. More...
class  ipe::TransformTool
 A tool for transforming the selected objects on the canvas. More...

Detailed Description

A widget (control) that displays an Ipe document page.

This module contains the classes needed to display and edit Ipe objects using the selected toolkit.

These classes are not in Ipelib, but in a separate library libipecanvas.


ipe-7.1.4/build/doc/classipe_1_1_ps_writer.html0000644000175000017500000002140712120621776021255 0ustar otfriedotfried Ipelib: ipe::PsWriter Class Reference
ipe::PsWriter Class Reference

#include <ipepswriter.h>

Public Member Functions

 PsWriter (TellStream &stream, const Document *doc, bool noColor)
 ~PsWriter ()
bool createHeader (int pno=0, int vno=0)
void createPageView (int pno=0, int vno=0)
void createXml (int compressLevel)
void createTrailer ()

Detailed Description

Create Postscript file.

This class is responsible for the creation of a Postscript file from the data. You have to create an PsWriter first, providing a stream that has been opened for (binary) writing and is empty.

Constructor & Destructor Documentation

PsWriter::PsWriter ( TellStream stream,
const Document doc,
bool  noColor 
)

Create Postscript writer operating on this (open and empty) file.

PsWriter::~PsWriter ( )

Destructor.

Member Function Documentation

bool PsWriter::createHeader ( int  pno = 0,
int  view = 0 
)

Create the document header and prolog (the resources).

Embeds no fonts if pool is 0. Returns false if a TrueType font is present.

void PsWriter::createPageView ( int  pno = 0,
int  vno = 0 
)

Create contents and page stream for this view.

Background is not shown.

void PsWriter::createXml ( int  compressLevel)

Save information in XML format.

void PsWriter::createTrailer ( )

Create the trailer of the Postscript file.


The documentation for this class was generated from the following files:
  • ipepswriter.h
  • ipepswriter.cpp

ipe-7.1.4/build/doc/classipe_1_1_stream-members.html0000644000175000017500000001332212120621776022157 0ustar otfriedotfried Ipelib: Member List
ipe::Stream Member List

This is the complete list of members for ipe::Stream, including all inherited members.

close()ipe::Streamvirtual
operator<<(char ch)ipe::Streaminline
operator<<(const String &s)ipe::Streaminline
operator<<(const char *s)ipe::Streaminline
operator<<(int i)ipe::Stream
operator<<(double d)ipe::Stream
putChar(char ch)=0ipe::Streampure virtual
putCString(const char *s)ipe::Streamvirtual
putHexByte(char b)ipe::Stream
putRaw(const char *data, int size)ipe::Streamvirtual
putString(String s)ipe::Streamvirtual
putXmlString(String s)ipe::Stream
~Stream()ipe::Streamvirtual

ipe-7.1.4/build/doc/ftv2splitbar.png0000644000175000017500000000047212120621776017155 0ustar otfriedotfried‰PNG  IHDRM¸¿IDATxíÝ¡JCa‡ñç(˜ ëƒ%±Ø4 b±È˜Í¶3˜v^Á±˜…ãó–ŽELƒõ…¥•³ ,ÿb;íç{Ã/¼ðÞÀaYÕ¯åóøq:¼º¹›\òIIIIIIIIIIIIIIIIII-Òçl¹›«õ抢è_t/Ï»ã£ÑíYQVõðêäíã÷´×ùY¬Úÿµ§¦ivók¾_íåýÛ£I@$I@$I@$I@$I@$I@$I@$I@$I@$I@$I@$I@$I@$I@$I@$I@$I@$I@$ýC[Vì=ü[„fÆIEND®B`‚ipe-7.1.4/build/doc/classipe_1_1_bitmap_finder-members.html0000644000175000017500000001075012120621776023471 0ustar otfriedotfried Ipelib: Member List
ipe::BitmapFinder Member List

This is the complete list of members for ipe::BitmapFinder, including all inherited members.

iBitmapsipe::BitmapFinder
scanPage(const Page *page)ipe::BitmapFinder
visitGroup(const Group *obj)ipe::BitmapFindervirtual
visitImage(const Image *obj)ipe::BitmapFindervirtual
visitPath(const Path *obj)ipe::Visitorvirtual
visitReference(const Reference *obj)ipe::Visitorvirtual
visitText(const Text *obj)ipe::Visitorvirtual
~Visitor()ipe::Visitorvirtual

ipe-7.1.4/build/doc/classipe_1_1_fonts-members.html0000644000175000017500000000671612120621776022026 0ustar otfriedotfried Ipelib: Member List
ipe::Fonts Member List

This is the complete list of members for ipe::Fonts, including all inherited members.

freetypeVersion()ipe::Fontsstatic
getFace(int id)ipe::Fonts
New(const FontPool *fontPool)ipe::Fontsstatic
screenFont()ipe::Fontsstatic
~Fonts()ipe::Fonts

ipe-7.1.4/build/doc/example3.svg0000644000175000017500000001224012120621776016260 0ustar otfriedotfried ipe-7.1.4/build/doc/classipe_1_1_face-members.html0000644000175000017500000000771312120621776021571 0ustar otfriedotfried Ipelib: Member List
ipe::Face Member List

This is the complete list of members for ipe::Face, including all inherited members.

cairoFont()ipe::Faceinline
Face(int id, const Font &font)ipe::Face
getGlyph(int ch)ipe::Face
matches(int id) const ipe::Faceinline
type() const ipe::Faceinline
width(int ch) const ipe::Faceinline
~Face()ipe::Face

ipe-7.1.4/build/doc/functions_0x71.html0000644000175000017500000001072312120621776017502 0ustar otfriedotfried Ipelib: Class Members
Here is a list of all class members with links to the classes they belong to:

- q -


ipe-7.1.4/build/doc/manual_35.html0000644000175000017500000000673112120621776016503 0ustar otfriedotfried Ipe Manual -- 8.1 Sharing Latex definitions with your Latex document
8.2 Writing ipelets8 Advanced topics8.1 Sharing Latex definitions with your Latex document

8.1 Sharing Latex definitions with your Latex document

When using Ipe figures in a Latex document, it is convenient to have access to some of the definitions from the document.

Ipe comes with a Lua script update-master that makes this easy.

In your Latex document, say master.tex, surround the interesting definitions using %%BeginIpePreamble and %%EndIpePreamble, for instance like this:

  %%BeginIpePreamble
  \usepackage{amsfonts}
  \newcommand{\R}{\mathbb{R}}
  %%EndIpePreamble

Running the script as

  ipescript update-master master.tex
extracts these definitions and saves them as a stylesheet master-preamble.isy. (This filename is fixed, and does not depend on the document name.)

Running this script as

  ipescript update-master master.tex figures/*.ipe
creates the stylesheet master-preamble.isy as above. In addition, it looks at all the Ipe figures mentioned on the command line. The script adds the new stylesheet to each figure, or updates the stylesheet to the newest version (if the figure already contains a stylesheet named "master-preamble").
ipe-7.1.4/build/doc/classipe_1_1_a85_source.html0000644000175000017500000001245312120621776021215 0ustar otfriedotfried Ipelib: ipe::A85Source Class Reference

#include <ipeutils.h>

Inherits ipe::DataSource.

Public Member Functions

 A85Source (DataSource &source)
virtual int getChar ()
- Public Member Functions inherited from ipe::DataSource
virtual ~DataSource ()=0

Detailed Description

Filter source adding ASCII85 decoding.

Constructor & Destructor Documentation

A85Source::A85Source ( DataSource source)

Member Function Documentation

int A85Source::getChar ( )
virtual

Get one more character, or EOF.

Implements ipe::DataSource.


The documentation for this class was generated from the following files:
  • ipeutils.h
  • ipeutils.cpp

ipe-7.1.4/build/doc/functions_func_0x66.html0000644000175000017500000002315212120621776020521 0ustar otfriedotfried Ipelib: Class Members - Functions
 

- f -


ipe-7.1.4/build/doc/classipe_1_1_curve-members.html0000644000175000017500000002315612120621776022016 0ustar otfriedotfried Ipelib: Member List
ipe::Curve Member List

This is the complete list of members for ipe::Curve, including all inherited members.

addToBBox(Rect &box, const Matrix &m, bool cp) const ipe::Curvevirtual
appendArc(const Matrix &m, const Vector &v0, const Vector &v1)ipe::Curve
appendBezier(const Vector &v0, const Vector &v1, const Vector &v2, const Vector &v3)ipe::Curve
appendQuad(const Vector &v0, const Vector &v1, const Vector &v2)ipe::Curve
appendSegment(const Vector &v0, const Vector &v1)ipe::Curve
appendSpline(const std::vector< Vector > &v)ipe::Curve
asClosedSpline() const ipe::SubPathvirtual
asCurve() const ipe::Curvevirtual
asEllipse() const ipe::SubPathvirtual
closed() const ipe::Curveinlinevirtual
closingSegment(Vector u[2]) const ipe::Curve
countSegments() const ipe::Curveinline
Curve()ipe::Curve
distance(const Vector &v, const Matrix &m, double bound) const ipe::Curvevirtual
draw(Painter &painter) const ipe::Curvevirtual
EClosedSpline enum valueipe::SubPath
ECurve enum valueipe::SubPath
EEllipse enum valueipe::SubPath
save(Stream &stream) const ipe::Curvevirtual
segment(int i) const ipe::Curve
setClosed(bool closed)ipe::Curve
snapBnd(const Vector &mouse, const Matrix &m, Vector &pos, double &bound) const ipe::Curvevirtual
snapVtx(const Vector &mouse, const Matrix &m, Vector &pos, double &bound) const ipe::Curvevirtual
type() const ipe::Curvevirtual
Type enum nameipe::SubPath
~SubPath()=0ipe::SubPathpure virtual

ipe-7.1.4/build/doc/classipe_1_1_pdf_obj.html0000644000175000017500000003727012120621776020647 0ustar otfriedotfried Ipelib: ipe::PdfObj Class Reference

#include <ipepdfparser.h>

Inherited by ipe::PdfArray, ipe::PdfBool, ipe::PdfDict, ipe::PdfName, ipe::PdfNull, ipe::PdfNumber, ipe::PdfRef, and ipe::PdfString.

Public Member Functions

virtual ~PdfObj ()=0
virtual const PdfNullnull () const
virtual const PdfBoolboolean () const
virtual const PdfNumbernumber () const
virtual const PdfStringstring () const
virtual const PdfNamename () const
virtual const PdfRefref () const
virtual const PdfArrayarray () const
virtual const PdfDictdict () const
virtual void write (Stream &stream) const =0
String repr () const

Detailed Description

Abstract base class for PDF objects.

Constructor & Destructor Documentation

PdfObj::~PdfObj ( )
pure virtual

Pure virtual destructor.

Member Function Documentation

const PdfNull * PdfObj::null ( ) const
virtual

Return this object as PDF null object.

Reimplemented in ipe::PdfNull.

const PdfBool * PdfObj::boolean ( ) const
virtual

Return this object as PDF bool object.

Reimplemented in ipe::PdfBool.

const PdfNumber * PdfObj::number ( ) const
virtual

Return this object as PDF number object.

Reimplemented in ipe::PdfNumber.

const PdfString * PdfObj::string ( ) const
virtual

Return this object as PDF string object.

Reimplemented in ipe::PdfString.

const PdfName * PdfObj::name ( ) const
virtual

Return this object as PDF name object.

Reimplemented in ipe::PdfName.

const PdfRef * PdfObj::ref ( ) const
virtual

Return this object as PDF reference object.

Reimplemented in ipe::PdfRef.

const PdfArray * PdfObj::array ( ) const
virtual

Return this object as PDF array object.

Reimplemented in ipe::PdfArray.

const PdfDict * PdfObj::dict ( ) const
virtual

Return this object as PDF dictionary object.

Reimplemented in ipe::PdfDict.

virtual void ipe::PdfObj::write ( Stream stream) const
pure virtual
String PdfObj::repr ( ) const

Return PDF representation of the object.


The documentation for this class was generated from the following files:
  • ipepdfparser.h
  • ipepdfparser.cpp

ipe-7.1.4/build/doc/functions_func_0x6e.html0000644000175000017500000001442012120621776020576 0ustar otfriedotfried Ipelib: Class Members - Functions
 

- n -


ipe-7.1.4/build/doc/namespaceipeqt.html0000644000175000017500000000321112120621776017704 0ustar otfriedotfried Ipelib: ipeqt Namespace Reference
ipeqt Namespace Reference

ipe-7.1.4/build/doc/classipe_1_1_a85_stream-members.html0000644000175000017500000001377412120621776022647 0ustar otfriedotfried Ipelib: Member List
ipe::A85Stream Member List

This is the complete list of members for ipe::A85Stream, including all inherited members.

A85Stream(Stream &stream)ipe::A85Stream
close()ipe::A85Streamvirtual
operator<<(char ch)ipe::Streaminline
operator<<(const String &s)ipe::Streaminline
operator<<(const char *s)ipe::Streaminline
operator<<(int i)ipe::Stream
operator<<(double d)ipe::Stream
putChar(char ch)ipe::A85Streamvirtual
putCString(const char *s)ipe::Streamvirtual
putHexByte(char b)ipe::Stream
putRaw(const char *data, int size)ipe::Streamvirtual
putString(String s)ipe::Streamvirtual
putXmlString(String s)ipe::Stream
~Stream()ipe::Streamvirtual

ipe-7.1.4/build/doc/ipelets.html0000644000175000017500000000572612120621776016367 0ustar otfriedotfried Ipelib: Ipelets
Ipelets

Ipe is an extensible drawing editor, and you can write extensions to Ipe that will appear on the Ipe menu and can be called from inside Ipe like other Ipe functions.

Ipe extensions are called Ipelets. They are most easily written in the language Lua (www.lua.org), in which also most of Ipe's user interface is written. Lua is a high-level interpreted language, in which interesting classes like vectors, matrices, and Ipe objects are made available. See Programming in Lua for more information about programming with Ipelib in Lua.

Ipelets written in Lua explains how to write ipelets in Lua.

Often, however, you will already have code that provides some geometric computation in another programming language such as C++. In such a situation you can create Lua bindings for your code and use it from your Lua ipelet. Creating Lua bindings is not documented here, as Ipe also provides an easier solution that will suffice in many cases. You can implement your ipelet entirely in C++, and only need some boilerplate code in Lua that defines the labels and functions inside the ipelet. Ipe will take care of loading and calling your C++ code.

Ipelets written in C++ explains how to write ipelets in C++.


ipe-7.1.4/build/doc/functions_func_0x7a.html0000644000175000017500000001104312120621776020571 0ustar otfriedotfried Ipelib: Class Members - Functions
 

- z -


ipe-7.1.4/build/doc/classipe_1_1_string_stream-members.html0000644000175000017500000001460412120621776023551 0ustar otfriedotfried Ipelib: Member List
ipe::StringStream Member List

This is the complete list of members for ipe::StringStream, including all inherited members.

close()ipe::Streamvirtual
operator<<(char ch)ipe::Streaminline
operator<<(const String &s)ipe::Streaminline
operator<<(const char *s)ipe::Streaminline
operator<<(int i)ipe::Stream
operator<<(double d)ipe::Stream
putChar(char ch)ipe::StringStreamvirtual
putCString(const char *s)ipe::StringStreamvirtual
putHexByte(char b)ipe::Stream
putRaw(const char *data, int size)ipe::StringStreamvirtual
putString(String s)ipe::StringStreamvirtual
putXmlString(String s)ipe::Stream
StringStream(String &string)ipe::StringStream
tell() const ipe::StringStreamvirtual
~Stream()ipe::Streamvirtual

ipe-7.1.4/build/doc/functions_func_0x78.html0000644000175000017500000001110112120621776020513 0ustar otfriedotfried Ipelib: Class Members - Functions
 

- x -


ipe-7.1.4/build/doc/functions_func_0x6c.html0000644000175000017500000001766612120621776020613 0ustar otfriedotfried Ipelib: Class Members - Functions
 

- l -


ipe-7.1.4/build/doc/classipe_1_1_string_stream.html0000644000175000017500000002300512120621776022114 0ustar otfriedotfried Ipelib: ipe::StringStream Class Reference
ipe::StringStream Class Reference

#include <ipebase.h>

Inherits ipe::TellStream.

Public Member Functions

 StringStream (String &string)
virtual void putChar (char ch)
virtual void putString (String s)
virtual void putCString (const char *s)
virtual void putRaw (const char *data, int size)
virtual long tell () const

Detailed Description

Stream writing into an String.

Constructor & Destructor Documentation

StringStream::StringStream ( String string)

Construct with string reference.

Member Function Documentation

void StringStream::putChar ( char  ch)
virtual

Output character.

Implements ipe::Stream.

void StringStream::putString ( String  s)
virtual

Output string.

Default implementation uses PutChar.

Reimplemented from ipe::Stream.

void StringStream::putCString ( const char *  s)
virtual

Output C string.

Default implementation uses PutChar.

Reimplemented from ipe::Stream.

void StringStream::putRaw ( const char *  data,
int  size 
)
virtual

Output raw character data.

Default implementation uses PutChar.

Reimplemented from ipe::Stream.

long StringStream::tell ( ) const
virtual

Implements ipe::TellStream.


The documentation for this class was generated from the following files:
  • ipebase.h
  • ipebase.cpp

ipe-7.1.4/build/doc/structipe_1_1_layout-members.html0000644000175000017500000001025112120621776022416 0ustar otfriedotfried Ipelib: Member List
ipe::Layout Member List

This is the complete list of members for ipe::Layout, including all inherited members.

iCropipe::Layout
iFrameSizeipe::Layout
iOriginipe::Layout
iPaperSizeipe::Layout
iParagraphSkipipe::Layout
isNull() const ipe::Layoutinline
Layout()ipe::Layoutinline
paper() const ipe::Layoutinline

ipe-7.1.4/build/doc/classipe_1_1_style_sheet-members.html0000644000175000017500000003150712120621776023221 0ustar otfriedotfried Ipelib: Member List
ipe::StyleSheet Member List

This is the complete list of members for ipe::StyleSheet, including all inherited members.

add(Kind kind, Attribute name, Attribute value)ipe::StyleSheet
addCMap(String s)ipe::StyleSheet
addEffect(Attribute name, const Effect &e)ipe::StyleSheet
addGradient(Attribute name, const Gradient &s)ipe::StyleSheet
addSymbol(Attribute name, const Symbol &symbol)ipe::StyleSheet
addTiling(Attribute name, const Tiling &s)ipe::StyleSheet
allCMaps(std::vector< String > &seq) const ipe::StyleSheet
allNames(Kind kind, AttributeSeq &seq) const ipe::StyleSheet
encoding() const ipe::StyleSheetinline
fillRule() const ipe::StyleSheetinline
find(Kind, Attribute sym) const ipe::StyleSheet
findEffect(Attribute sym) const ipe::StyleSheet
findGradient(Attribute sym) const ipe::StyleSheet
findSymbol(Attribute sym) const ipe::StyleSheet
findTiling(Attribute sym) const ipe::StyleSheet
has(Kind kind, Attribute sym) const ipe::StyleSheet
isStandard() const ipe::StyleSheetinline
layout() const ipe::StyleSheet
lineCap() const ipe::StyleSheetinline
lineJoin() const ipe::StyleSheetinline
name() const ipe::StyleSheetinline
pageNumberStyle()ipe::StyleSheet
preamble() const ipe::StyleSheetinline
saveAsXml(Stream &stream, bool saveBitmaps=false) const ipe::StyleSheet
setEncoding(const String &enc)ipe::StyleSheetinline
setFillRule(TFillRule s)ipe::StyleSheet
setLayout(const Layout &margins)ipe::StyleSheet
setLineCap(TLineCap s)ipe::StyleSheet
setLineJoin(TLineJoin s)ipe::StyleSheet
setName(const String &name)ipe::StyleSheetinline
setPageNumberStyle(const PageNumberStyle &pns)ipe::StyleSheet
setPreamble(const String &str)ipe::StyleSheetinline
setTextPadding(const TextPadding &pad)ipe::StyleSheet
setTitleStyle(const TitleStyle &ts)ipe::StyleSheet
standard()ipe::StyleSheetstatic
StyleSheet()ipe::StyleSheet
textPadding() const ipe::StyleSheet
titleStyle() const ipe::StyleSheet

ipe-7.1.4/build/doc/classipe_1_1_attribute.html0000644000175000017500000017445612120621776021257 0ustar otfriedotfried Ipelib: ipe::Attribute Class Reference

#include <ipeattributes.h>

Public Member Functions

 Attribute ()
 Attribute (bool symbolic, String name)
 Attribute (Fixed value)
 Attribute (Color color)
 Attribute (THorizontalAlignment align)
 Attribute (TVerticalAlignment align)
 Attribute (TLineJoin join)
 Attribute (TLineCap cap)
 Attribute (TFillRule rule)
 Attribute (TPinned pin)
 Attribute (TTransformations trans)
 Attribute (TPathMode pm)
bool isSymbolic () const
bool isString () const
bool isColor () const
bool isNumber () const
bool isEnum () const
bool isBoolean () const
bool isNormal () const
int index () const
int internal () const
String string () const
Fixed number () const
Color color () const
bool boolean () const
THorizontalAlignment horizontalAlignment () const
TVerticalAlignment verticalAlignment () const
TLineJoin lineJoin () const
TLineCap lineCap () const
TFillRule fillRule () const
TPinned pinned () const
TTransformations transformations () const
TPathMode pathMode () const
bool operator== (const Attribute &rhs) const
bool operator!= (const Attribute &rhs) const

Static Public Member Functions

static Attribute Boolean (bool flag)
static Attribute BLACK ()
static Attribute WHITE ()
static Attribute ONE ()
static Attribute NORMAL ()
static Attribute UNDEFINED ()
static Attribute BACKGROUND ()
static Attribute SYM_STROKE ()
static Attribute SYM_FILL ()
static Attribute SYM_PEN ()
static Attribute ARROW_NORMAL ()
static Attribute OPAQUE ()
static Attribute ARROW_ARC ()
static Attribute ARROW_FARC ()
static Attribute makeColor (String str, Attribute deflt)
static Attribute makeScalar (String str, Attribute deflt)
static Attribute makeDashStyle (String str)
static Attribute makeTextSize (String str)
static Attribute normal (Kind kind)

Friends

class StyleSheet

Detailed Description

An attribute of an Ipe Object.

An attribute is either an absolute value or a symbolic name that has to be looked up in a StyleSheet.

All string values are replaced by indices into a Repository (that applies both to symbolic names and to absolute values that are strings). All other values are stored directly inside the attribute, either as a Fixed or a Color.

There are five different kinds of Attribute objects:

  • if isSymbolic() is true, index() returns the index into the repository, and string() returns the symbolic name.
  • if isColor() is true, color() returns an absolute RGB color.
  • if isNumeric() is true, number() returns an absolute scalar value.
  • if isEnum() is true, the attribute represents an enumeration value.
  • otherwise, isString() is true, and index() returns the index into the repository (for a string expressing the absolute value of the attribute), and string() returns the string itself.

Constructor & Destructor Documentation

ipe::Attribute::Attribute ( )
inlineexplicit

Default constructor.

Attribute::Attribute ( bool  symbolic,
String  name 
)
explicit

Create an attribute with string value.

Attribute::Attribute ( Fixed  value)
explicit

Create an absolute numeric attribute.

Attribute::Attribute ( Color  color)
explicit

Create an attribute with absolute color.

ipe::Attribute::Attribute ( THorizontalAlignment  align)
inlineexplicit
ipe::Attribute::Attribute ( TVerticalAlignment  align)
inlineexplicit
ipe::Attribute::Attribute ( TLineJoin  join)
inlineexplicit
ipe::Attribute::Attribute ( TLineCap  cap)
inlineexplicit
ipe::Attribute::Attribute ( TFillRule  rule)
inlineexplicit
ipe::Attribute::Attribute ( TPinned  pin)
inlineexplicit
ipe::Attribute::Attribute ( TTransformations  trans)
inlineexplicit
ipe::Attribute::Attribute ( TPathMode  pm)
inlineexplicit

Member Function Documentation

static Attribute ipe::Attribute::Boolean ( bool  flag)
inlinestatic
bool ipe::Attribute::isSymbolic ( ) const
inline

Is it symbolic?

bool ipe::Attribute::isString ( ) const
inline

Is it an absolute string value?

bool ipe::Attribute::isColor ( ) const
inline

Is it a color?

bool ipe::Attribute::isNumber ( ) const
inline

Is it a number?

bool ipe::Attribute::isEnum ( ) const
inline

Is it an enumeration?

bool ipe::Attribute::isBoolean ( ) const
inline

Is it a boolean?

bool ipe::Attribute::isNormal ( ) const
inline

Is it the symbolic name "normal"?

int ipe::Attribute::index ( ) const
inline

Return index into Repository.

int ipe::Attribute::internal ( ) const
inline
String Attribute::string ( ) const

Return string representing the attribute.

Fixed Attribute::number ( ) const

Return value of absolute numeric attribute.

Color Attribute::color ( ) const

Return absolute color.

bool ipe::Attribute::boolean ( ) const
inline
THorizontalAlignment ipe::Attribute::horizontalAlignment ( ) const
inline
TVerticalAlignment ipe::Attribute::verticalAlignment ( ) const
inline
TLineJoin ipe::Attribute::lineJoin ( ) const
inline
TLineCap ipe::Attribute::lineCap ( ) const
inline
TFillRule ipe::Attribute::fillRule ( ) const
inline
TPinned ipe::Attribute::pinned ( ) const
inline
TTransformations ipe::Attribute::transformations ( ) const
inline
TPathMode ipe::Attribute::pathMode ( ) const
inline
bool ipe::Attribute::operator== ( const Attribute rhs) const
inline

Are two values equal (only compares index!)

bool ipe::Attribute::operator!= ( const Attribute rhs) const
inline

Are two values different (only compares index!)

static Attribute ipe::Attribute::BLACK ( )
inlinestatic

Create absolute black color.

static Attribute ipe::Attribute::WHITE ( )
inlinestatic

Create absolute white color.

static Attribute ipe::Attribute::ONE ( )
inlinestatic

Create absolute number one.

static Attribute ipe::Attribute::NORMAL ( )
inlinestatic

Create symbolic attribute "normal".

static Attribute ipe::Attribute::UNDEFINED ( )
inlinestatic

Create symbolic attribute "undefined".

static Attribute ipe::Attribute::BACKGROUND ( )
inlinestatic

Create symbolic attribute "Background".

static Attribute ipe::Attribute::SYM_STROKE ( )
inlinestatic

Create symbolic attribute "sym-stroke".

static Attribute ipe::Attribute::SYM_FILL ( )
inlinestatic

Create symbolic attribute "sym-fill".

static Attribute ipe::Attribute::SYM_PEN ( )
inlinestatic

Create symbolic attribute "sym-pen".

static Attribute ipe::Attribute::ARROW_NORMAL ( )
inlinestatic

Create symbolic attribute "arrow/normal(spx)".

static Attribute ipe::Attribute::OPAQUE ( )
inlinestatic

Create symbolic attribute "opaque".

static Attribute ipe::Attribute::ARROW_ARC ( )
inlinestatic

Create symbolic attribute "arrow/arc(spx)".

static Attribute ipe::Attribute::ARROW_FARC ( )
inlinestatic

Create symbolic attribute "arrow/farc(spx)".

Attribute Attribute::makeColor ( String  str,
Attribute  deflt 
)
static

Make a color attribute.

If the string starts with a letter, make a symbolic attribute. Otherwise, it's either a single gray value (0.0 to 1.0), or the three red, green, and blue components, separated by spaces. If it's an empty string, return deflt.

Attribute Attribute::makeScalar ( String  str,
Attribute  deflt 
)
static

Make a scalar attribute.

If str is empty, simply return deflt. If str starts with a letter, make a symbolic attribute. Otherwise, must be a number.

Attribute Attribute::makeDashStyle ( String  str)
static

Construct dash style attribute from string.

Strings starting with '[' create an absolute dash style. The empty string is equivalent to 'normal'. Any other string creates a symbolic dash style.

Attribute Attribute::makeTextSize ( String  str)
static

Construct text size attribute from string.

String starting with digit creates a numeric absolute value, string starting with letter creates symbolic text size, anything else creates absolute (string) text size. The empty string is treated like "normal".

Attribute Attribute::normal ( Kind  kind)
static

Return a standard value for attribute of kind.

The value is used if the stylesheet doesn't define a symbolic attribute used in the document.

Friends And Related Function Documentation

friend class StyleSheet
friend

The documentation for this class was generated from the following files:
  • ipeattributes.h
  • ipeattributes.cpp

ipe-7.1.4/build/doc/classipe_1_1_base64_stream.html0000644000175000017500000002363312120621776021701 0ustar otfriedotfried Ipelib: ipe::Base64Stream Class Reference
ipe::Base64Stream Class Reference

#include <ipeutils.h>

Inherits ipe::Stream.

Public Member Functions

 Base64Stream (Stream &stream)
virtual void putChar (char ch)
virtual void close ()
- Public Member Functions inherited from ipe::Stream
virtual ~Stream ()
virtual void putString (String s)
virtual void putCString (const char *s)
virtual void putRaw (const char *data, int size)
Streamoperator<< (char ch)
Streamoperator<< (const String &s)
Streamoperator<< (const char *s)
Streamoperator<< (int i)
Streamoperator<< (double d)
void putHexByte (char b)
void putXmlString (String s)

Detailed Description

Filter stream adding Base64 encoding.

Constructor & Destructor Documentation

Base64Stream::Base64Stream ( Stream stream)

Member Function Documentation

void Base64Stream::putChar ( char  ch)
virtual

Output character.

Implements ipe::Stream.

void Base64Stream::close ( )
virtual

Close the stream. No more writing allowed!

Reimplemented from ipe::Stream.


The documentation for this class was generated from the following files:
  • ipeutils.h
  • ipeutils.cpp

ipe-7.1.4/build/doc/classipe_1_1_linear-members.html0000644000175000017500000001362212120621776022141 0ustar otfriedotfried Ipelib: Member List
ipe::Linear Member List

This is the complete list of members for ipe::Linear, including all inherited members.

aipe::Linear
determinant() const ipe::Linearinline
inverse() const ipe::Linear
isIdentity() const ipe::Linearinline
Linear()ipe::Linearinline
Linear(Angle angle)ipe::Linearexplicit
Linear(double m11, double m21, double m12, double m22)ipe::Linearinlineexplicit
Linear(String str)ipe::Linearexplicit
operator*(const Vector &rhs) const ipe::Linearinline
operator*(const Vector &rhs) constipe::Linearrelated
operator*(const Linear &lhs, const Linear &rhs)ipe::Linearrelated
operator<<(Stream &stream, const Linear &rhs)ipe::Linearrelated
operator==(const Linear &rhs) const ipe::Linearinline

ipe-7.1.4/build/doc/manual_48.html0000644000175000017500000000462512120621776016507 0ustar otfriedotfried Ipe Manual -- 12 Command line options and environment variables
13 History and acknowledgmentsTop11 Using Ipe figures in Latex12 Command line options and environment variables

12 Command line options and environment variables

ipe-7.1.4/build/doc/classipe_1_1_fixed-members.html0000644000175000017500000001366612120621776021776 0ustar otfriedotfried Ipelib: Member List
ipe::Fixed Member List

This is the complete list of members for ipe::Fixed, including all inherited members.

Fixed(int val)ipe::Fixedinlineexplicit
Fixed()ipe::Fixedinlineexplicit
fromDouble(double val)ipe::Fixedstatic
fromInternal(int val)ipe::Fixedinlinestatic
internal() const ipe::Fixedinline
mult(int a, int b) const ipe::Fixed
operator!=(const Fixed &rhs) const ipe::Fixedinline
operator<(const Fixed &rhs) const ipe::Fixedinline
operator<<(Stream &stream, const Fixed &f)ipe::Fixedfriend
operator<<(Stream &stream, const Fixed &f)ipe::Fixedrelated
operator==(const Fixed &rhs) const ipe::Fixedinline
toDouble() const ipe::Fixedinline
toInt() const ipe::Fixedinline

ipe-7.1.4/build/doc/classipe_1_1_pdf_ref-members.html0000644000175000017500000001343212120621776022273 0ustar otfriedotfried Ipelib: Member List
ipe::PdfRef Member List

This is the complete list of members for ipe::PdfRef, including all inherited members.

array() const ipe::PdfObjvirtual
boolean() const ipe::PdfObjvirtual
dict() const ipe::PdfObjvirtual
name() const ipe::PdfObjvirtual
null() const ipe::PdfObjvirtual
number() const ipe::PdfObjvirtual
PdfRef(int val)ipe::PdfRefinlineexplicit
ref() const ipe::PdfRefvirtual
repr() const ipe::PdfObj
string() const ipe::PdfObjvirtual
value() const ipe::PdfRefinline
write(Stream &stream) const ipe::PdfRefvirtual
~PdfObj()=0ipe::PdfObjpure virtual

ipe-7.1.4/build/doc/functions_0x75.html0000644000175000017500000001251512120621776017507 0ustar otfriedotfried Ipelib: Class Members
Here is a list of all class members with links to the classes they belong to:

- u -


ipe-7.1.4/build/doc/dir_91a90e6e897462a7bb8a7a0fc103953b.html0000644000175000017500000000755612120621776022067 0ustar otfriedotfried Ipelib: /home/otfried/Devel/ipe/src/ipecanvas/ Directory Reference
ipecanvas Directory Reference

Files

file  ipecanvas.cpp
file  ipecanvas.h
file  ipecanvas_gtk.cpp
file  ipecanvas_gtk.h
file  ipecanvas_qt.cpp
file  ipecanvas_qt.h
file  ipecanvas_win.cpp
file  ipecanvas_win.h
file  ipeselector_qt.cpp
file  ipeselector_qt.h
file  ipetool.cpp
file  ipetool.h

ipe-7.1.4/build/doc/manual_7.html0000644000175000017500000000720312120621776016415 0ustar otfriedotfried Ipe Manual -- 3.4 Stroke and fill colors
3.5 Pen, dash style, arrows, and tiling patterns3 General Concepts3.3 Moving and scaling objects3.4 Stroke and fill colors

3.4 Stroke and fill colors

Path objects can have two different colors, one for the boundary and one for the interior of the object. The Postscript terms stroke and fill are used to denote these two colors. Stroke and fill color can be selected independently in the Properties window. Imagine preparing a drawing by hand, using a pen and black ink. What Ipe draws in its stroke color is what you would stroke in black ink with your pen. Probably you would not use your pen to fill objects, but you would use a brush, and maybe even a different kind of paint like water color. Well, the fill color is Ipe's "brush".

When you create a path object, you'll have to tell Ipe whether you want it stroked, filled, or both. This is set in the Path properties field. Clicking near the right end of the field will cycle through the three modes "stroked", "stroked & filled", and "filled." You can also use the context menu of the path properties field.

Text objects and arrows only use the stroke color, even for the filled arrows. You would also use a pen for these details, not the brush.

The mark shapes "disk" and "square" also use only the stroke color. You can make bicolored marks using the mark shapes "fdisk" and "fsquare".

ipe-7.1.4/build/doc/functions_func_0x70.html0000644000175000017500000003431712120621776020521 0ustar otfriedotfried Ipelib: Class Members - Functions
 

- p -


ipe-7.1.4/build/doc/tab_s.png0000644000175000017500000000027012120621776015617 0ustar otfriedotfried‰PNG  IHDR$ÇÇ[IDATxíÝ ‚@@Ñ£?Q…¤"š¢%¦I‘—Šf–6[´HÃäQƒ<Þâõþ]ždr Í’s?ˆO=Ñññw'ÌF‡Ž íðö-~rÃ[œèŠ­ì¬mƒÖ¬ƒݯнŠÕF)Yº% §`nÌ,9B ™’©!ÑŒ\ý<Å#üîî•IEND®B`‚ipe-7.1.4/build/doc/functions_func_0x68.html0000644000175000017500000001376412120621776020533 0ustar otfriedotfried Ipelib: Class Members - Functions
 

- h -


ipe-7.1.4/build/doc/structipe_1_1_text_1_1_x_form-members.html0000644000175000017500000000746612120621776024115 0ustar otfriedotfried Ipelib: Member List
ipe::Text::XForm Member List

ipe-7.1.4/build/doc/manual_32.html0000644000175000017500000001401012120621776016465 0ustar otfriedotfried Ipe Manual -- 7.4 Gradient patterns
7.5 Ipe symbols used from text objects7 Presentations7.3 Bookmarks7.4 Gradient patterns

7.4 Gradient patterns

Gradient patterns allow to shade objects with continuously changing colors. This is often used for backgrounds, or to achieve the illusion of three-dimensional spheres or cylinders. Note that documents containing gradient patterns cannot be saved in EPS format.

The intended use of gradients is to allow the creation of attractive symbols inside the style sheet, for backgrounds, as bullets in item lists (see next section), or simply to define attractive glassy-ball symbols and the like that can be used through the Use symbol ipelet.

The Ipe user interface does not offer any way of creating or editing gradients. If your stylesheet defines a gradient, then it is possible to fill a path object with this gradient, but getting the gradient coordinate system right is not trivial. (The trick is to draw the path object at gradient coordinates, and translate/rotate it to the final location afterwards.)

The definition of a linear (axial) gradient looks like this:

  <gradient name="linear" type="axial" extend="yes" coords="75 0 325 0">
    <stop offset="0.05" color="1 0.4 0"/>
    <stop offset="0.95" color="1 1 0.4"/>
  </gradient>
If used like this:
  <path stroke="0" fill="1" gradient="linear" pen="3">
    50 50 m 350 50 l 350 150 l 50 150 l h
  </path>
it will look like this:

A radial gradient looks like this:
  <gradient name="radial" type="radial" extend="yes"
  	    coords="200 100 0 200 100 150">
    <stop offset="0" color="1 0 0"/>
    <stop offset="0.5" color="0 0 1"/>
    <stop offset="1" color="1 0 0"/>
  </gradient>
It will look like this:

A common use of radial gradients is to define glassy balls like this:
  <gradient name="ball" type="radial" coords="-4 10 2 0 0 18">
    <stop offset="0" color="1 1 1"/>
    <stop offset="1" color="0 0 1"/>
  </gradient>
Note that the gradient is centered at 0 0, so it needs to be moved to the location where it is used:
  <path matrix="3 0 0 3 100 100" fill="1" gradient="ball">
    18 0 0 18 0 0 e
  </path>

Normally, you would define a symbol looking like a glassy ball in your style sheet:
<ipestyle>
  <gradient name="ball" type="radial" coords="-4 10 2 0 0 18">
    <stop offset="0" color="1 1 1"/>
    <stop offset="1" color="0 0 1"/>
  </gradient>
  <symbol name="ball(x)" transformations="translations">
    <path fill="1" gradient="ball"> 18 0 0 18 0 0 e </path>
  </symbol>
</ipestyle>
The glassy ball can then be used in the document using the Use symbol ipelet. Note that transformations="translations" ensures that stretching your drawing does not change the glassy ball. Adding the (x) suffix to the symbol name allows you to resize the glassy ball by changing the symbol size from the properties (the same selector used to change the mark size).

For the precise syntax of the gradient definition see here. The easiest method of creating gradients, though, is to use an SVG editor such as Inkscape and to convert the SVG gradient to Ipe format using Svgtoipe.

ipe-7.1.4/build/doc/classipe_1_1_pdf_file-members.html0000644000175000017500000000722512120621776022441 0ustar otfriedotfried Ipelib: Member List
ipe::PdfFile Member List

This is the complete list of members for ipe::PdfFile, including all inherited members.

catalog() const ipe::PdfFile
object(int num) const ipe::PdfFile
page() const ipe::PdfFile
parse(DataSource &source)ipe::PdfFile
PdfFile()ipe::PdfFile
~PdfFile()ipe::PdfFile

ipe-7.1.4/build/doc/functions_0x6b.html0000644000175000017500000001142412120621776017561 0ustar otfriedotfried Ipelib: Class Members
Here is a list of all class members with links to the classes they belong to:

- k -


ipe-7.1.4/build/doc/classipe_1_1_repository.html0000644000175000017500000001715612120621776021464 0ustar otfriedotfried Ipelib: ipe::Repository Class Reference

#include <ipeattributes.h>

Public Member Functions

String toString (int index) const
int toIndex (String str)

Static Public Member Functions

static Repositoryget ()
static void cleanup ()

Detailed Description

Repository of strings.

Ipe documents can use symbolic attributes, such as 'normal', 'fat', or 'thin' for line thickness, or 'red', 'navy', 'turquoise' for color, as well as absolute attributes such as "[3 1] 0" for a dash pattern. To avoid storing these common strings hundreds of times, Repository keeps a repository of strings. Inside an Object, strings are replaced by indices into the repository.

The Repository is a singleton object. It is created the first time it is used. You obtain access to the repository using get().

Member Function Documentation

Repository * Repository::get ( )
static

Get pointer to singleton Repository.

void Repository::cleanup ( )
static

Destroy repository object.

String Repository::toString ( int  index) const

Return string with given index.

int Repository::toIndex ( String  str)

Return index of given string.

The string is added to the repository if it doesn't exist yet.


The documentation for this class was generated from the following files:
  • ipeattributes.h
  • ipeattributes.cpp

ipe-7.1.4/build/doc/manual_30.html0000644000175000017500000001235012120621776016470 0ustar otfriedotfried Ipe Manual -- 7.2 Views
7.3 Bookmarks7 Presentations7.1 Presentation stylesheets7.2 Views

7.2 Views

When making a PDF presentation with Acrobat Reader, one would often like to present a page incrementally. For instance, I would first like to show a polygon, then add its triangulation, and finally color the vertices. Views make it possible to do this nicely.

An Ipe document consists of several pages, each of which can consist of an arbitrary number of views. When saving as PDF, each view generates a separate PDF page (if you only look at the result in, say, Acrobat reader, you cannot tell whether two pages are actually two views of the same Ipe page or two different Ipe pages).

An Ipe page consists of a number of objects, a number of layers, and a number of views. Each object belongs to exactly one layer. A layer can be shown by any number of views—a view is really just a list of layers to be presented. In addition, a view keeps a record of the current active layer—this makes it easy to move around your views and edit them. Finally, views can specify a graphic effect to be used by the PDF viewer when proceeding to the following PDF page.

To return to our polygon triangulation example, let's create an empty page. We draw a polygon into the default layer "alpha." Now use the New layer, new view function (in the Views menu), and draw the triangulation into the new layer "beta." Note that the function not only created a new layer, but also a second view showing both "alpha" and "beta". Try moving back and forth between the two views (using the PageUp and PageDown keys). You'll see changes in the layer list on the left: in view 1, layer "alpha" is selected and active, in view 2, both layers are selected and "beta" is active. Create a third layer and view, and mark the vertices.

Save in PDF format, and voila, you have a lovely little presentation. The result is available here.

In presentations, one often has slides with mostly text. The textbox object is convenient for this, as one doesn't need to use the mouse to create it. To create a slide where several text items appear one by one, one only needs to press F10 to create a textbox, then Shift+Ctrl+I to make a new view, F10 again for the next textbox, and so on. Finally, one moves the textboxes vertically for the most pleasing effect (Shift+Alt+Left Mouse does a constrained vertical translation, or Shift+Left Mouse in Translate mode).

Note that all views of a page receive the same bounding box, containing all objects visible on some view, plus all objects in a layer named "BBOX" (even if that layer is not visible). This can be used to force a larger bounding box without adding a white rectangle or the like.

If you need independent bounding boxes for each view (as in Ipe 6), create a layer named "VIEWBBOX". Any view in which this layer is visible will receive a bounding box computed for the objects visible in this view only.

ipe-7.1.4/build/doc/structipe_1_1_pdf_token-members.html0000644000175000017500000001453212120621776023060 0ustar otfriedotfried Ipelib: Member List
ipe::PdfToken Member List

This is the complete list of members for ipe::PdfToken, including all inherited members.

EArrayBg enum valueipe::PdfToken
EArrayEnd enum valueipe::PdfToken
EDictBg enum valueipe::PdfToken
EDictEnd enum valueipe::PdfToken
EErr enum valueipe::PdfToken
EFalse enum valueipe::PdfToken
EName enum valueipe::PdfToken
ENull enum valueipe::PdfToken
ENumber enum valueipe::PdfToken
EOp enum valueipe::PdfToken
EString enum valueipe::PdfToken
ETrue enum valueipe::PdfToken
iStringipe::PdfToken
iTypeipe::PdfToken
TToken enum nameipe::PdfToken

ipe-7.1.4/build/doc/classipe_1_1_ipelet.html0000644000175000017500000001465512120621776020530 0ustar otfriedotfried Ipelib: ipe::Ipelet Class Reference

#include <ipelet.h>

Public Member Functions

virtual ~Ipelet ()=0
virtual int ipelibVersion () const =0
virtual bool run (int function, IpeletData *data, IpeletHelper *helper)=0

Detailed Description

Abstract base class for Ipelets.

Constructor & Destructor Documentation

Ipelet::~Ipelet ( )
pure virtual

Pure virtual destructor.

Member Function Documentation

virtual int ipe::Ipelet::ipelibVersion ( ) const
pure virtual

Return the version of Ipelib the Ipelet was linked against.

virtual bool ipe::Ipelet::run ( int  function,
IpeletData data,
IpeletHelper helper 
)
pure virtual

Run a function from the Ipelet.

Return true if page was changed and undo registration is necessary.


The documentation for this class was generated from the following files:
  • ipelet.h
  • ipeutils.cpp

ipe-7.1.4/build/doc/structipe_1_1_gradient.html0000644000175000017500000002173512120621776021257 0ustar otfriedotfried Ipelib: ipe::Gradient Struct Reference

#include <ipeattributes.h>

Classes

struct  Stop
 A color stop. More...

Public Types

enum  TType { EAxial = 2, ERadial = 3 }

Public Attributes

TType iType
Vector iV [2]
double iRadius [2]
bool iExtend
Matrix iMatrix
std::vector< StopiStops

Detailed Description

A gradient pattern.

Member Enumeration Documentation

There are two types of gradients, along an axis or between two circles.

Enumerator:
EAxial 
ERadial 

Member Data Documentation

TType ipe::Gradient::iType

The type of gradient: axial or radial.

Vector ipe::Gradient::iV[2]

The coordinates of the axis endpoints, or the two circle centers.

double ipe::Gradient::iRadius[2]

The radii of the two circles (not used for axial gradients).

bool ipe::Gradient::iExtend

Whether to extend the gradient beyond the endpoints.

Matrix ipe::Gradient::iMatrix

Gradient transformation.

std::vector<Stop> ipe::Gradient::iStops

The color stops.


The documentation for this struct was generated from the following file:
  • ipeattributes.h

ipe-7.1.4/build/doc/classipe_1_1_sub_path.html0000644000175000017500000005700212120621776021044 0ustar otfriedotfried Ipelib: ipe::SubPath Class Reference

#include <ipeshape.h>

Inherited by ipe::ClosedSpline, ipe::Curve, and ipe::Ellipse.

Public Types

enum  Type { ECurve, EEllipse, EClosedSpline }

Public Member Functions

virtual ~SubPath ()=0
virtual Type type () const =0
virtual bool closed () const
virtual const EllipseasEllipse () const
virtual const ClosedSplineasClosedSpline () const
virtual const CurveasCurve () const
virtual void save (Stream &stream) const =0
virtual void draw (Painter &painter) const =0
virtual void addToBBox (Rect &box, const Matrix &m, bool cp) const =0
virtual double distance (const Vector &v, const Matrix &m, double bound) const =0
virtual void snapVtx (const Vector &mouse, const Matrix &m, Vector &pos, double &bound) const =0
virtual void snapBnd (const Vector &mouse, const Matrix &m, Vector &pos, double &bound) const =0

Detailed Description

A subpath of a Path.

A subpath is either open, or closed. There are two special kinds of closed subpaths, namely ellipses and closed B-splines.

Member Enumeration Documentation

The subpath types.

Enumerator:
ECurve 
EEllipse 
EClosedSpline 

Constructor & Destructor Documentation

SubPath::~SubPath ( )
pure virtual

Implementation of pure virtual destructor.

Member Function Documentation

virtual Type ipe::SubPath::type ( ) const
pure virtual

Return type of this subpath.

Implemented in ipe::Curve, ipe::ClosedSpline, and ipe::Ellipse.

bool SubPath::closed ( ) const
virtual

Is this subpath closed?

Default implementation returns true.

Reimplemented in ipe::Curve.

const Ellipse * SubPath::asEllipse ( ) const
virtual

Return this object as an Ellipse, or 0 if it's not an ellipse.

Reimplemented in ipe::Ellipse.

const ClosedSpline * SubPath::asClosedSpline ( ) const
virtual

Return this object as an ClosedSpline, or 0 if it's not a closed spline.

Reimplemented in ipe::ClosedSpline.

const Curve * SubPath::asCurve ( ) const
virtual

Return this object as an Curve, or else 0.

Reimplemented in ipe::Curve.

virtual void ipe::SubPath::save ( Stream stream) const
pure virtual

Save subpath to XML stream.

Implemented in ipe::Curve, ipe::ClosedSpline, and ipe::Ellipse.

virtual void ipe::SubPath::draw ( Painter painter) const
pure virtual

Draw subpath (does not call drawPath()).

Implemented in ipe::Curve, ipe::ClosedSpline, and ipe::Ellipse.

virtual void ipe::SubPath::addToBBox ( Rect box,
const Matrix m,
bool  cp 
) const
pure virtual

Add subpath to box.

Implemented in ipe::Curve, ipe::ClosedSpline, and ipe::Ellipse.

virtual double ipe::SubPath::distance ( const Vector v,
const Matrix m,
double  bound 
) const
pure virtual

Return distance from v to subpath transformed by m.

Implemented in ipe::Curve, ipe::ClosedSpline, and ipe::Ellipse.

virtual void ipe::SubPath::snapVtx ( const Vector mouse,
const Matrix m,
Vector pos,
double &  bound 
) const
pure virtual

Snap to vertex.

Implemented in ipe::Curve, ipe::ClosedSpline, and ipe::Ellipse.

virtual void ipe::SubPath::snapBnd ( const Vector mouse,
const Matrix m,
Vector pos,
double &  bound 
) const
pure virtual

Snap to boundary of subpath.

Implemented in ipe::Curve, ipe::ClosedSpline, and ipe::Ellipse.


The documentation for this class was generated from the following files:
  • ipeshape.h
  • ipeshape.cpp

ipe-7.1.4/build/doc/functions_func_0x6f.html0000644000175000017500000002727112120621776020607 0ustar otfriedotfried Ipelib: Class Members - Functions
ipe-7.1.4/build/doc/functions_func_0x75.html0000644000175000017500000001245212120621776020522 0ustar otfriedotfried Ipelib: Class Members - Functions
 

- u -


ipe-7.1.4/build/doc/manual_6.html0000644000175000017500000000761212120621776016420 0ustar otfriedotfried Ipe Manual -- 3.3 Moving and scaling objects
3.4 Stroke and fill colors3 General Concepts3.2 The current selection3.3 Moving and scaling objects

3.3 Moving and scaling objects

There are three modes for transforming objects: translate, stretch, and rotate. If you hold the shift key while pressing the left mouse button, the stretch function keeps the aspect ratio of the objects (an operation we call scaling), and the translate function is restricted to horizontal and vertical translations.

Normally, the transformation functions work on the current selection. However, to make it more convenient to move around many different objects, there is an exception: When the mouse button is pressed while the cursor is not near the current selection, but there is some other object close to the cursor, that object is moved, rotated, or scaled instead.

By default, the rotate function rotates around the center of the bounding box for the selected objects. This behavior can be overridden by specifying an axis system. If an axis system is set, then the origin is used as the center.

The scale and stretch functions use a corner of the bounding box for the selected objects as the fix-point of the transformation. Again, if an axis system is set, the origin of the system is used instead.

It is often convenient to rotate or scale around a vertex of an object. This is easy to achieve by setting the origin of the axis system to that vertex, using the Snap to vertex function for setting the axis system.

ipe-7.1.4/build/doc/next.png0000644000175000017500000000211412120621776015504 0ustar otfriedotfried‰PNG  IHDR D¤ŠÆsRGB®ÎégAMA± üa cHRMz&€„ú€èu0ê`:˜pœºQ<PLTEÿÿÿ™ÌÿÂõ†¹ì|¯âs¦ÙiœÏ_’ÅV‰¼L²Cv©:m 0c–&YŒPƒ =p3fŸ‰ñ pHYsÄÄ•+©IDAT8OÍ“Éà CÙZ(ËÿmM2°¦×øÞ€ÉÆþóD žpjÛEæ>¦ùI쀫LT'„bÓ7&¾°žÐ ÖF!"x‚>'!†ð«Ëe…Q­Y!Ÿ÷ž ˜šö2§dˆtßhdCuáÄDyh€_…ÓP€ Yd”E”óŠ[4·7*̬ËU¨EÃR–M¤OÜÇ4Ë„ûp_¦GnÖºí?h“qÍtZIEND®B`‚ipe-7.1.4/build/doc/functions_0x7e.html0000644000175000017500000002167712120621776017600 0ustar otfriedotfried Ipelib: Class Members
Here is a list of all class members with links to the classes they belong to:

- ~ -


ipe-7.1.4/build/doc/functions_0x7a.html0000644000175000017500000001126712120621776017566 0ustar otfriedotfried Ipelib: Class Members
Here is a list of all class members with links to the classes they belong to:

- z -


ipe-7.1.4/build/doc/manual_45.html0000644000175000017500000003404712120621776016505 0ustar otfriedotfried Ipe Manual -- 9.4 The <ipestyle> element
9 The Ipe file format9.3 Ipe object elements9.4 The <ipestyle> element

9.4 The <ipestyle> element

Attributes

name
(optional) The name serves to identify the style sheet informally, and can be used to automatically update the style sheet from a file with the matching name.

The contents of the <ipestyle> element is a series of style definition elements, in no particular order. These elements are described below.

9.4.1 The <symbol> element

Attributes

name
(required) The name identifies the symbol and must be unique in the style sheet. For parameterized symbols, the name must end with the pattern "(s?f?p?x?)", where "s" stands for stroke, "f" for fill, "p" for pen, and "x" for size.
transformations
(optional) As for objects.
xform
(optional) If this attribute is set, a PDF XForm will be created for this symbol when saving or exporting to PDF. It implies transformations="translations", and will be ignored if any of the symbol parameters (that is, stroke, fill, pen, or size) are used. Setting this attribute will cause the PDF output to be significantly smaller for a complicated symbol that is used often (for instance, a complicated background used on every page).

The contents of the <symbol> element is a single Ipe object.

9.4.2 The <preamble> element

See the <preamble> elements inside <ipe> elements.

9.4.3 The <cmap> element

Attributes

font
(required) The name of a font. The font is marked as being Unicode-encoded. See here for an example.

9.4.4 The <textstyle> element

Attributes

name
(required) The symbolic name (to be used in the style attribute of <text> elements),
begin
(required) LaTeX code to be placed before the text of the object when it is formatted,
end
(required) LaTeX code to be placed after the text of the object when it is formatted.

9.4.5 The <layout> element

It defines the layout of the frame on the paper and the paper size.

Attributes

paper
(required) The size of the paper.
origin
(required) The lower left corner of the frame in the paper coordinate system.
frame
(required) The size of the frame.
skip
(optional) The default paragraph skip between textboxes.
crop
(optional) If the value of crop is yes, Ipe will create a CropBox attribute when saving to PDF.

9.4.6 The <titlestyle> element

It defines the appearance of the page title on the page.

Attributes

pos
(required) The position of the title reference point in the frame coordinate system.
color
(required) The color of the title.
size
(required) The title font size (same as for <text> elements).
halign
(optional) The horizontal alignment (same as for <text> elements).
valign
(optional) The vertical alignment (same as for <text> elements).

9.4.7 The <pagenumberstyle> element

It defines the appearance of page numbers on the page.

Attributes

pos
(required) The position of the page number on the page.
color
(required) The color of the page number as an absolute color.
size
(required) The font size as a number.

9.4.8 The <textpad> element

It defines padding around text objects for the computation of bounding boxes. The four required attributes are left, right, top, and bottom.

9.4.9 The <pathstyle> element

It defines the default setting for path objects.

Attributes

cap
(optional) Same as for <path> elements.
join
(optional) Same as for <path> elements.
fillrule
(optional) Same as for <path> elements.

9.4.10 The <opacity> element

The opacity element defines a possible opacity value (also known as an alpha-value). All opacity values used in a document must be defined in the style sheet.

Attributes

name
(required) A symbolic name, to be used in the opacity attribute of a text or path element.
value
(required) An absolute value for the opacity, between 0.001 and 1.000. A value of 1.0 implies that the element is fully opaque.

9.4.11 The <gradient> element

The gradient element defines a gradient pattern.

Attributes of <gradient>

name
(required) The symbolic name (to be used in the gradient attribute of <path> elements).
type
(required) Possible values are axial and radial.
extend
(optional) yes or no (the default). Indicates whether the gradient is extended beyond the boundaries.
coords
(required) For axial shading: the coordinates of the endpoints of the axis (in the order x1 y1 x2 y2). For radial shading: the center and radius of both circles (in the order cx1 cy1 r1 cx2 cy2 r2).
matrix
(optional) A transformation that transforms the gradient coordinate system into the coordinate system of the path object using the gradient. The default is the identity matrix.

The contents of the <gradient> element are <stop> elements defining the color stops of the gradient. There must be at least two stops. Stops must be defined in increasing offset order. It is not necessary that the first offset is 0.0 and the last one is 1.0.

Attributes of <stop>

offset
(required) Offset of the color stop (a number between 0.0 and 1.0).
color
(required) Color at this color stop (three numbers). Symbolic names are not allowed.

9.4.12 The <tiling> element

The tiling element defines a tiling pattern. Only very simple patterns that hatch the area with a line are supported.

Attributes

name
(required) The symbolic name (to be used in the tiling attribute of <path> elements).
angle
(required) Slope of the hatching line in degrees, between -90 and +90 degrees.
width
(required) Width of the hatching line.
step
(required) Distance from one hatching line to the next.

Here, width and step are measured in the y-direction if the absolute value of angle is less than 45 degrees, and in the y-direction otherwise.

9.4.13 The <effect> element

The effect element defines a graphic effect to be used during a PDF page transition. Acrobat Reader supports these effects, but not all PDF viewers do.

Attributes

name
(required) The symbolic name (to be used in the effect attribute of <view> elements).
duration
(required) Value must be a real number, indicating the duration of display in seconds.
transition
(required) Value must be a real number, indicating the duration of the transition effect in seconds.
effect
(required) a number indicated the desired effect. The value must be an integer between 0 and 16 (see ipe::Effect::TEffect for the exact meaning).

9.4.14 Other style definition elements

The remaining style definition elements are:

  • <color> Defines a symbolic color. The value must be an absolute color, that is either a single gray value (between 0 and 1), or three components (red, green, blue) seperated by space.
  • <dashstyle> Defines a symbolic dashstyle. The value must be a correct dashstyle description, e.g. [3 5 2 5] 0.
  • <pen> Defines a symbolic pen width. The value is a single real number.
  • <textsize> Defines a symbolic text size. The value is a piece of LaTeX source code selecting the desired font size.
  • <textstretch> Defines a symbolic text stretch factor. The symbolic name is shared with <textsize> elements. The value is a single real number.
  • <symbolsize> Defines a symbolic size for symbols. The value is a single real number, and indicates the scaling factor used for the symbol.
  • <arrowsize> Defines a symbolic size for arrows. The value is a single real number.
  • <gridsize> Defines a grid size. The symbolic name cannot actually be used by objects in the document — it is only used to fill the grid size selector in the user interface.
  • <anglesize> Defines an angular snap angle. The symbolic name cannot actually be used by objects in the document — it is only used to fill the angle selector in the user interface.

Common attributes

name
(required) A symbolic name, which must start with a letter 'a' to 'z' or 'A' to 'Z'.
value
(required) A legal absolute value for the type of attribute.
ipe-7.1.4/build/doc/ftv2pnode.png0000644000175000017500000000034512120621776016441 0ustar otfriedotfried‰PNG  IHDRɪ|¬IDATxí=QF‘Ø¥D«ÔkÄ:‰F©PK؃=V@§Õ³ Õ8SHxñÌ0bnrróŠ{ò½¿¾’$ ÀÏTŠP  ö¼X¬OÛd6êìòð"°²S´±O¥B€(¡àQé)š+YĈ ÒªËRÉÐ>VtÉsˆm9(ê„䜥k‚-@ȧ-Ü$ó b Ò[he ¿Kp-ôl|CùÿApRG'rÍ­aIEND®B`‚ipe-7.1.4/build/doc/previous.png0000644000175000017500000000212512120621776016404 0ustar otfriedotfried‰PNG  IHDR D¤ŠÆsRGB®ÎégAMA± üa cHRMz&€„ú€èu0ê`:˜pœºQ<PLTEÿÿÿ™ÌÿÂõ†¹ì|¯âs¦ÙiœÏ_’ÅV‰¼L²Cv©:m 0c–&YŒPƒFy =p3f sx pHYsÄÄ•+²IDAT8O͓˃ EyµXÅÿÿÙB.P…@·fåLŽÌÉ%ù§ÄÓë©^W¯«äv¦ ææý”£þ~ïË èú^5sÀêo],°è/}lèY&VXý G@A­#Na&ýÓI¡ 7¨O<Á΀w j†’DÆA³»“€<ÆÞ¦L?P¢Ž;Ih¬£$e…ɺÜ&Fi–¥:¤¢­ £íc§ñ¸‡3NròÄ¿?q-L¢ÚIEND®B`‚ipe-7.1.4/build/doc/functions_0x69.html0000644000175000017500000007767612120621776017535 0ustar otfriedotfried Ipelib: Class Members
Here is a list of all class members with links to the classes they belong to:

- i -


ipe-7.1.4/build/doc/ftv2ns.png0000644000175000017500000000060412120621776015752 0ustar otfriedotfried‰PNG  IHDRÚ}\ˆKIDATxíÝ1K1Àñ­ž ØG•â‚n‚Šà ‚âælÁE¿€‹“ (nºêââêäࢋƒÐMAá@°‹ µât¾ÄK¡à%Ü•Û ý]BIïå%áuÍ…a™€,e × v¯ç¥«ˆi‹º¨Õö–î\tòòuénÄ0ã æÜÉoV\Ì$G.&@Y=ÆË%$um·¢ûÛ6–'Úß«9Qó\bÙ)²º0Ðë-Zœ¥TèHÍ`pÀcsm µö5:>Áë‡Þ¦I µØ ‚F‹Çà]» ›jg—ìoÏáõ©[ œõ š­onë €Ô¬¨vqõ„?\Ðç”  6»øüÒTe ÃÉéŸeç ÀÅlQ ¡c”€ª¬ü3*d€ÅWTMÏ\rÿÿh6™ø1±F ‹°fžIEND®B`‚ipe-7.1.4/build/doc/structipe_1_1_style_sheet_1_1_title_style.html0000644000175000017500000001656412120621776025077 0ustar otfriedotfried Ipelib: ipe::StyleSheet::TitleStyle Struct Reference
ipe::StyleSheet::TitleStyle Struct Reference

#include <ipestyle.h>

Public Attributes

bool iDefined
Vector iPos
Attribute iSize
Attribute iColor
THorizontalAlignment iHorizontalAlignment
TVerticalAlignment iVerticalAlignment

Detailed Description

Style of the title on a page.

Member Data Documentation

bool ipe::StyleSheet::TitleStyle::iDefined

Has a TitleStyle been defined in the style sheet?

Vector ipe::StyleSheet::TitleStyle::iPos

Position on the page (in Ipe coordinate system)

Attribute ipe::StyleSheet::TitleStyle::iSize

Text size.

Attribute ipe::StyleSheet::TitleStyle::iColor

Text color.

THorizontalAlignment ipe::StyleSheet::TitleStyle::iHorizontalAlignment

Horizontal alignment.

TVerticalAlignment ipe::StyleSheet::TitleStyle::iVerticalAlignment

Vertical alignment.


The documentation for this struct was generated from the following file:
  • ipestyle.h

ipe-7.1.4/build/doc/functions_func_0x63.html0000644000175000017500000003472612120621776020527 0ustar otfriedotfried Ipelib: Class Members - Functions
 

- c -


ipe-7.1.4/build/doc/functions_0x70.html0000644000175000017500000003524312120621776017505 0ustar otfriedotfried Ipelib: Class Members
Here is a list of all class members with links to the classes they belong to:

- p -


ipe-7.1.4/build/doc/manual_9.html0000644000175000017500000000557312120621776016427 0ustar otfriedotfried Ipe Manual -- 3.6 Transparency
3.7 Symbolic and absolute attributes3 General Concepts3.5 Pen, dash style, arrows, and tiling patterns3.6 Transparency

3.6 Transparency

Ipe supports a simple model of transparency. You can set the opacity of path objects and text objects: an opacity of 1.0 means a fully opaque object, while 0.5 would mean that the object is half-transparent. All opacity values you wish to use in a document must be defined in its stylesheet.

Documents containing transparency cannot be saved in EPS format. (Postscript does not support transparency.) For this reason, the standard Ipe stylesheet (that is automatically added to newly created documents) does not define opacity values, and so you must use a custom stylesheet to make use of transparency in your document.

ipe-7.1.4/build/doc/functions_func_0x6b.html0000644000175000017500000001136112120621776020574 0ustar otfriedotfried Ipelib: Class Members - Functions
 

- k -


ipe-7.1.4/build/doc/classipe_1_1_line.html0000644000175000017500000003323612120621776020171 0ustar otfriedotfried Ipelib: ipe::Line Class Reference

#include <ipegeo.h>

Public Member Functions

 Line ()
 Line (const Vector &p, const Vector &dir)
double side (const Vector &p) const
Vector normal () const
double distance (const Vector &v) const
bool intersects (const Line &line, Vector &pt)
Vector project (const Vector &v) const
Vector dir () const

Static Public Member Functions

static Line through (const Vector &p, const Vector &q)

Public Attributes

Vector iP

Detailed Description

A directed line.

Constructor & Destructor Documentation

ipe::Line::Line ( )
inlineexplicit

Create default line (x-axis).

Line::Line ( const Vector p,
const Vector dir 
)
explicit

Construct a line from p with direction dir.

Asserts unit length of dir.

Member Function Documentation

Line Line::through ( const Vector p,
const Vector q 
)
static

Construct a line through two points.

double Line::side ( const Vector p) const

Result is > 0, = 0, < 0 if point lies to the left, on, to the right.

Vector ipe::Line::normal ( ) const
inline

Return a normal vector pointing to the left of the directed line.

double Line::distance ( const Vector v) const

Returns distance between line and v.

bool Line::intersects ( const Line line,
Vector pt 
)

Does this line intersect line? If so, computes intersection point.

Vector Line::project ( const Vector v) const

Orthogonally project point v onto the line.

Vector ipe::Line::dir ( ) const
inline

Return direction of line.

Member Data Documentation

Vector ipe::Line::iP

Point on the line.


The documentation for this class was generated from the following files:
  • ipegeo.h
  • ipegeo.cpp

ipe-7.1.4/build/doc/classipe_1_1_tool.html0000644000175000017500000003115712120621776020217 0ustar otfriedotfried Ipelib: ipe::Tool Class Reference

#include <ipetool.h>

Inherited by ipe::PanTool, ipe::SelectTool, and ipe::TransformTool.

Public Member Functions

virtual ~Tool ()
virtual void draw (Painter &painter) const =0
virtual void mouseButton (int button, bool press)
virtual void mouseMove ()
virtual bool key (int code, int modifiers, String text)

Protected Member Functions

 Tool (CanvasBase *canvas)

Protected Attributes

CanvasBaseiCanvas

Detailed Description

Abstract base class for various canvas tools.

The Canvas doesn't know about the various modes for object creation, editing, and moving, but delegates the handling to a subclass of Tool.

Constructor & Destructor Documentation

Tool::~Tool ( )
virtual

Virtual destructor.

Tool::Tool ( CanvasBase canvas)
protected

Constructor.

Member Function Documentation

virtual void ipe::Tool::draw ( Painter painter) const
pure virtual
void Tool::mouseButton ( int  button,
bool  press 
)
virtual

Called when a mouse button is pressed or released on the canvas.

button is 1, 2, or 3, with Shift/Ctrl/Alt/Meta modifiers added in (as defined in CanvasBase::TModifiers. press is true for button-down, and false for button-up.

Reimplemented in ipe::TransformTool, ipe::SelectTool, and ipe::PanTool.

void Tool::mouseMove ( )
virtual

Called when the mouse is moved on the canvas.

Reimplemented in ipe::TransformTool, ipe::SelectTool, and ipe::PanTool.

bool Tool::key ( int  code,
int  modifiers,
String  text 
)
virtual

Called when a key is pressed.

modifiers are as defined in CanvasBase::TModifiers.

Reimplemented in ipe::SelectTool.

Member Data Documentation

CanvasBase* ipe::Tool::iCanvas
protected

The documentation for this class was generated from the following files:
  • ipetool.h
  • ipetool.cpp

ipe-7.1.4/build/doc/classipe_1_1_pdf_writer.html0000644000175000017500000002520212120621776021401 0ustar otfriedotfried Ipelib: ipe::PdfWriter Class Reference
ipe::PdfWriter Class Reference

#include <ipepdfwriter.h>

Public Member Functions

 PdfWriter (TellStream &stream, const Document *doc, const FontPool *pool, bool markedView, int fromPage, int toPage, int compression)
 ~PdfWriter ()
void createPages ()
void createPageView (int page, int view)
void createBookmarks ()
void createXmlStream (String xmldata, bool preCompressed)
void createTrailer ()

Detailed Description

Create PDF file.

This class is responsible for the creation of a PDF file from the Ipe data. You have to create a PdfWriter first, providing a file that has been opened for (binary) writing and is empty. Then call createPages() to embed the pages. Optionally, call createXmlStream to embed a stream with the XML representation of the document. Finally, call createTrailer to complete the PDF document, and close the file.

Some reserved PDF object numbers:

  • 0: Must be left empty (a PDF restriction).
  • 1: XML stream.
  • 2: Parent of all pages objects.

Constructor & Destructor Documentation

PdfWriter::PdfWriter ( TellStream stream,
const Document doc,
const FontPool *  pool,
bool  markedView,
int  fromPage,
int  toPage,
int  compression 
)

Create a PDF writer operating on this (open and empty) file.

PdfWriter::~PdfWriter ( )

Destructor.

Member Function Documentation

void PdfWriter::createPages ( )

Create all PDF pages.

void PdfWriter::createPageView ( int  page,
int  view 
)

create contents and page stream for this page view.

void PdfWriter::createBookmarks ( )

Create the bookmarks (PDF outline).

void PdfWriter::createXmlStream ( String  xmldata,
bool  preCompressed 
)

Create a stream containing the XML data.

void PdfWriter::createTrailer ( )

Create the root objects and trailer of the PDF file.


The documentation for this class was generated from the following files:
  • ipepdfwriter.h
  • ipepdfwriter.cpp

ipe-7.1.4/build/doc/classipe_1_1_inflate_source-members.html0000644000175000017500000000655712120621776023702 0ustar otfriedotfried Ipelib: Member List
ipe::InflateSource Member List

This is the complete list of members for ipe::InflateSource, including all inherited members.

getChar()ipe::InflateSourcevirtual
InflateSource(DataSource &source)ipe::InflateSource
~DataSource()=0ipe::DataSourcepure virtual
~InflateSource()ipe::InflateSourcevirtual

ipe-7.1.4/build/doc/classipe_1_1_page_selector.html0000644000175000017500000002215612120621776022055 0ustar otfriedotfried Ipelib: ipe::PageSelector Class Reference

#include <ipeselector_qt.h>

Signals

void selectionMade ()

Public Member Functions

 PageSelector (Document *doc, int page, int startIndex, int width, QWidget *parent=0)
int selectedIndex () const

Static Public Member Functions

static int selectPageOrView (Document *doc, int page=-1, int startIndex=0, int pageWidth=240, int width=600, int height=480)

Constructor & Destructor Documentation

PageSelector::PageSelector ( Document doc,
int  page,
int  startIndex,
int  itemWidth,
QWidget *  parent = 0 
)

Construct the widget.

If page is negative, the last view of each page is shown. Otherwise, all views of this page are shown. itemWidth is the width of the page thumbnails (the height is computed automatically).

Member Function Documentation

int ipe::PageSelector::selectedIndex ( ) const
inline
int PageSelector::selectPageOrView ( Document doc,
int  page = -1,
int  startIndex = 0,
int  pageWidth = 240,
int  width = 600,
int  height = 480 
)
static

Show dialog to select a page or a view.

If page is negative (the default), shows thumbnails of all pages of the document in a dialog. If the user selects a page, the page number is returned. If the dialog is canceled, -1 is returned.

If page is non-negative, all views of this page are shown, and the selected view number is returned.

void ipe::PageSelector::selectionMade ( )
signal

The documentation for this class was generated from the following files:
  • ipeselector_qt.h
  • ipeselector_qt.cpp

ipe-7.1.4/build/doc/classipe_1_1_tell_stream-members.html0000644000175000017500000001401712120621776023201 0ustar otfriedotfried Ipelib: Member List
ipe::TellStream Member List

This is the complete list of members for ipe::TellStream, including all inherited members.

close()ipe::Streamvirtual
operator<<(char ch)ipe::Streaminline
operator<<(const String &s)ipe::Streaminline
operator<<(const char *s)ipe::Streaminline
operator<<(int i)ipe::Stream
operator<<(double d)ipe::Stream
putChar(char ch)=0ipe::Streampure virtual
putCString(const char *s)ipe::Streamvirtual
putHexByte(char b)ipe::Stream
putRaw(const char *data, int size)ipe::Streamvirtual
putString(String s)ipe::Streamvirtual
putXmlString(String s)ipe::Stream
tell() const =0ipe::TellStreampure virtual
~Stream()ipe::Streamvirtual

ipe-7.1.4/build/doc/classipe_1_1_group.html0000644000175000017500000014141312120621776020373 0ustar otfriedotfried Ipelib: ipe::Group Class Reference

#include <ipegroup.h>

Inherits ipe::Object.

Classes

struct  Imp

Public Types

typedef List::const_iterator const_iterator
- Public Types inherited from ipe::Object
enum  Type {
  EGroup, EPath, EText, EImage,
  EReference
}

Public Member Functions

 Group ()
 Group (const Group &rhs)
virtual ~Group ()
 Group (const XmlAttributes &attr)
Groupoperator= (const Group &rhs)
virtual Objectclone () const
virtual GroupasGroup ()
virtual Type type () const
virtual TPinned pinned () const
virtual void accept (Visitor &visitor) const
virtual void saveAsXml (Stream &stream, String layer) const
virtual void draw (Painter &painter) const
virtual void drawSimple (Painter &painter) const
virtual void addToBBox (Rect &box, const Matrix &m, bool cp) const
virtual double distance (const Vector &v, const Matrix &m, double bound) const
virtual void snapVtx (const Vector &mouse, const Matrix &m, Vector &pos, double &bound) const
virtual void snapBnd (const Vector &mouse, const Matrix &m, Vector &pos, double &bound) const
const Shapeclip () const
void setClip (const Shape &clip)
int count () const
const Objectobject (int i) const
const_iterator begin () const
const_iterator end () const
void push_back (Object *)
void saveComponentsAsXml (Stream &stream) const
virtual void checkStyle (const Cascade *sheet, AttributeSeq &seq) const
virtual bool setAttribute (Property prop, Attribute value, Attribute stroke, Attribute fill)
- Public Member Functions inherited from ipe::Object
virtual ~Object ()=0
virtual TextasText ()
virtual PathasPath ()
virtual ImageasImage ()
virtual ReferenceasReference ()
void setPinned (TPinned pin)
TTransformations transformations () const
void setTransformations (TTransformations trans)
void setMatrix (const Matrix &matrix)
const Matrixmatrix () const
virtual Attribute getAttribute (Property prop)

Additional Inherited Members

- Protected Member Functions inherited from ipe::Object
 Object ()
 Object (const AllAttributes &attr)
 Object (const Object &rhs)
 Object (const XmlAttributes &attr)
void saveAttributesAsXml (Stream &stream, String layer) const
- Static Protected Member Functions inherited from ipe::Object
static void checkSymbol (Kind kind, Attribute attr, const Cascade *sheet, AttributeSeq &seq)
- Protected Attributes inherited from ipe::Object
Matrix iMatrix
TPinned iPinned: 8
TTransformations iTransformations: 8

Detailed Description

The group object.

Ipe objects can be grouped together, and the resulting composite can be used like any Ipe object.

This is an application of the "Composite" pattern.

Member Typedef Documentation

typedef List::const_iterator ipe::Group::const_iterator

Constructor & Destructor Documentation

Group::Group ( )
explicit

Create empty group (objects can be added later).

Group::Group ( const Group rhs)

Copy constructor. Constant time — components are not copied!

Group::~Group ( )
virtual

Destructor.

Group::Group ( const XmlAttributes attr)
explicit

Create empty group with these attributes (objects can be added later).

Member Function Documentation

Group & Group::operator= ( const Group rhs)

Assignment operator (constant-time).

Object * Group::clone ( ) const
virtual

Clone a group object (constant-time).

Implements ipe::Object.

Group * Group::asGroup ( )
virtual

Return pointer to this object.

Reimplemented from ipe::Object.

Object::Type Group::type ( ) const
virtual

Implements ipe::Object.

TPinned Group::pinned ( ) const
virtual

Return total pinning status of group and its elements.

Reimplemented from ipe::Object.

void Group::accept ( Visitor visitor) const
virtual

Call visitGroup of visitor.

Implements ipe::Object.

void Group::saveAsXml ( Stream stream,
String  layer 
) const
virtual

Save the object in XML format.

Implements ipe::Object.

void Group::draw ( Painter painter) const
virtual

Draw the object.

Implements ipe::Object.

void Group::drawSimple ( Painter painter) const
virtual

Draw simple version for selecting and transforming.

Implements ipe::Object.

void Group::addToBBox ( Rect box,
const Matrix m,
bool  cp 
) const
virtual

Extend box to include the object transformed by m.

For objects in a page, don't call this directly. The Page caches the bounding box of each object, so it is far more efficient to call Page::bbox.

Control points that lie outside the visual object are included if cp is true.

If called with an empty box and cp == false, the result of this function is a tight bounding box for the object, with a little leeway in case the boundary is determined by a spline (it has to be approximated to perform this operation).

Implements ipe::Object.

double Group::distance ( const Vector v,
const Matrix m,
double  bound 
) const
virtual

Return distance of transformed object to point v. If larger than bound, can just return bound.

Implements ipe::Object.

void Group::snapVtx ( const Vector mouse,
const Matrix m,
Vector pos,
double &  bound 
) const
virtual

Compute possible vertex snapping position for transformed object.

Looks only for positions closer than bound. If successful, modify pos and bound.

Implements ipe::Object.

void Group::snapBnd ( const Vector mouse,
const Matrix m,
Vector pos,
double &  bound 
) const
virtual

Compute boundary snapping position for transformed object.

Looks only for positions closer than bound. If successful, modify pos and bound. The default implementation does nothing.

Reimplemented from ipe::Object.

const Shape& ipe::Group::clip ( ) const
inline
void Group::setClip ( const Shape clip)

Set clip path for this group.

Any previously set clip path is deleted.

int ipe::Group::count ( ) const
inline

Return number of component objects.

const Object* ipe::Group::object ( int  i) const
inline

Return object at index i.

const_iterator ipe::Group::begin ( ) const
inline

Return iterator for first object.

const_iterator ipe::Group::end ( ) const
inline

Return iterator for end of sequence.

void Group::push_back ( Object obj)

Add an object.

Takes ownership of the object. This will panic if the object shares its implementation! The method is only useful right after construction of the group.

void Group::saveComponentsAsXml ( Stream stream) const

Save all the components, one by one, in XML format.

void Group::checkStyle ( const Cascade sheet,
AttributeSeq seq 
) const
virtual

Check all symbolic attributes.

Reimplemented from ipe::Object.

bool Group::setAttribute ( Property  prop,
Attribute  value,
Attribute  stroke,
Attribute  fill 
)
virtual

Set attribute on all children.

Reimplemented from ipe::Object.


The documentation for this class was generated from the following files:
  • ipegroup.h
  • ipegroup.cpp

ipe-7.1.4/build/doc/functions_0x65.html0000644000175000017500000005560612120621776017516 0ustar otfriedotfried Ipelib: Class Members
Here is a list of all class members with links to the classes they belong to:

- e -


ipe-7.1.4/build/doc/ftv2lastnode.png0000644000175000017500000000012612120621776017142 0ustar otfriedotfried‰PNG  IHDRɪ|IDATxíݱðøScOx@ –¨y}IEND®B`‚ipe-7.1.4/build/doc/functions_0x79.html0000644000175000017500000001071012120621776017506 0ustar otfriedotfried Ipelib: Class Members
Here is a list of all class members with links to the classes they belong to:

- y -


ipe-7.1.4/build/doc/structipe_1_1_style_sheet_1_1_page_number_style.html0000644000175000017500000001333112120621776026227 0ustar otfriedotfried Ipelib: ipe::StyleSheet::PageNumberStyle Struct Reference
ipe::StyleSheet::PageNumberStyle Struct Reference

#include <ipestyle.h>

Public Attributes

bool iDefined
Vector iPos
double iFontSize
Color iColor

Detailed Description

How to show page numbers on the paper.

Member Data Documentation

bool ipe::StyleSheet::PageNumberStyle::iDefined

Has a PageNumberStyle been defined in the style sheet?

Vector ipe::StyleSheet::PageNumberStyle::iPos

Position on the page.

double ipe::StyleSheet::PageNumberStyle::iFontSize

Font size.

Color ipe::StyleSheet::PageNumberStyle::iColor

Text color.


The documentation for this struct was generated from the following file:
  • ipestyle.h

ipe-7.1.4/build/doc/manual_49.html0000644000175000017500000002414712120621776016511 0ustar otfriedotfried Ipe Manual -- 12.1 Command line options
12.2 Environment variables12 Command line options and environment variables12.1 Command line options

12.1 Command line options

Ipe command line options

Ipe supports the following command line options:

-sheet style sheet name
Adds the designated style sheet to any newly created documents.
-show-configuration
With this option, Ipe will display the current configuration options on stdout, and terminate.
In addition, you can specify the name of an Ipe file to open on the command line. Ipe also understands all options supported by the Qt library.

Ipeview: a minimal Ipe viewer

Ipeview allows you to quickly view an Ipe file without starting the Ipe program.

Ipetoipe: converting Ipe file formats

The auxiliary program ipetoipe converts between the different Ipe file formats:

  ipetoipe ( -xml | -pdf | -eps ) { <options> } infile [ outfile ]
The first argument determines the format of the output file. If no output filename is provided, Ipe will try to guess it by appending one of the extensions "ipe", "pdf", or "eps" to the input file's basename.

For example, the command line syntax

  ipetoipe -pdf figure1.eps
converts figure1.eps to figure1.pdf.

Ipetoipe understands the following options:

-export
No Ipe markup is included in the resulting output file. Ipe will not be able to open a file created that way, so make sure you keep your original!
-markedview
(PDF only)
Only the marked views of marked Ipe pages will be created in PDF format. If all views of a marked page are unmarked, the last view is exported. This is convenient to make handouts for slides.
-pages from-to
(PDF only)
Restrict exporting to PDF to this page range. This implies the -export option.
-view page-view
Only export this single view from the document. This implies the -export option.
-runlatex
Run Latex even for XML output. This has the effect of including the dimensions of each text object in the XML file.
-nocolor
Do not use any color commands in Postscript output. This is useful if you are preparing a manuscript for publication where the publisher checks that the figures are grayscale only. Note that this option doesn't actually verify that the figure con- tains no color (a figure using color processed with this option will cause a Postscript error when displayed).
-nozip
Do not compress streams in PDF or Postscript output.

Iperender: converting to a bitmap or SVG art

The program iperender converts a page of the document to a bitmap in PNG format or to scalable vector graphics in SVG format. (Of course the result contains no Ipe markup, so make sure you keep your original.) For instance, the following command line

  iperender -png -page 3 -resolution 150 presentation.pdf pres3.png
converts page 3 of the Ipe document presentation.pdf to a bitmap, with resolution 150 pixels per inch.

Ipeextract: extract XML stream from Ipe PDF or EPS file

Ipeextract extracts the XML stream from a PDF or EPS file and saves it in a file. It will work even if Ipe cannot actually parse the file, so you can use this tool to debug problems where Ipe fails to open your document.

ipeextract infile [ outfile ]
If not provided, the outfile is guessed by appending "xml" to the infile's basename.

Ipe6upgrade: convert Ipe 6 files to Ipe 7 file format

Ipe6upgrade takes as input a file created by any version of Ipe 6, and saves in the format of Ipe 7.0.0.

ipe6upgrade infile [ outfile ]
If not provided, the outfile is guessed by adding the extension "ipe" to the infile's basename.

Ipescript: running Ipe scripts

Ipescript runs an Ipe script written in the Lua language with bindings for the Ipe objects, such as the script "update-master". Ipescript automatically finds the script in Ipe's script directories. On Unix, you can place your own scripts in $HOME/.ipe/scripts.

The Ipe distribution contains the following scripts:

  • update-master, explained earlier;
  • add-style to add a stylesheet to Ipe figures;
  • update-styles to update the stylesheets in Ipe figures (in the same way that Ipe does it using the "Update stylesheets" function).

Svgtoipe: Importing SVG figures

The auxiliary program svgtoipe converts an SVG figure to Ipe format. It cannot handle all SVG features (many SVG features are not supported by Ipe anyway), but it works for gradients.

svgtoipe is not part of the Ipe source distribution. You can download it separately.

Pdftoipe: Importing Postscript and PDF

You can convert arbitrary Postscript or PDF files into Ipe documents, making them editable. The auxiliary program pdftoipe converts (pages from) a PDF file into an Ipe XML-file. (If your source is Postscript, you have to first convert it to PDF using Acrobat Distiller or ps2pdf.) Once converted to XML, the file can be opened from Ipe as usual.

The conversion process should handle any graphics in the PDF file fine, but doesn't do very well on text—Ipe's text model is just too different.

pdftoipe is not part of the Ipe source distribution. You can download and build it separately.

Ipe5toxml: convert Ipe 5 files to Ipe 6 file format

If you still have figures that were created with Ipe 5, you can use ipe5toxml to convert them to Ipe 6 format. You can then use ipe6upgrade to convert them to Ipe 7 format.

ipe5toxml is not part of the Ipe distribution, but available as a separate download.

Figtoipe: Importing FIG figures

The auxiliary program figtoipe converts a figure in FIG format into an Ipe XML-file. This is useful if you used to make figures with Xfig before discovering Ipe, of if your co-authors made figures for your article with Xfig (converting them will have the added benefit of forcing your co-authors to learn to use Ipe). Finally, there are quite a number of programs that can export to FIG format, and figtoipe effectively turns that into the possibility of exporting to Ipe.

However, figtoipe is not quite complete. The drawing models of FIG and Ipe are also somewhat different, which makes it impossible to properly render some FIG files in Ipe. Ipe does not support depth ordering independent of grouping, pattern fill, and Postscript fonts. You may therefore have to edit the file after conversion.

figtoipe is not part of the Ipe distribution. You can download and build it separately. figtoipe is now maintained by Alexander Bürger.

ipe-7.1.4/build/doc/classipe_1_1_bitmap_1_1_m_render_data.html0000644000175000017500000000741312120621776024020 0ustar otfriedotfried Ipelib: ipe::Bitmap::MRenderData Class Reference
ipe::Bitmap::MRenderData Class Reference

#include <ipebitmap.h>

Inherited by RenderData.

Public Member Functions

virtual ~MRenderData ()

Detailed Description

Abstract base class for pixmap data stored by a client.

Constructor & Destructor Documentation

Bitmap::MRenderData::~MRenderData ( )
virtual

The documentation for this class was generated from the following files:
  • ipebitmap.h
  • ipebitmap.cpp

ipe-7.1.4/build/doc/classipe_1_1_ellipse.html0000644000175000017500000004750312120621776020701 0ustar otfriedotfried Ipelib: ipe::Ellipse Class Reference

#include <ipeshape.h>

Inherits ipe::SubPath.

Public Member Functions

 Ellipse (const Matrix &m)
virtual Type type () const
virtual const EllipseasEllipse () const
Matrix matrix () const
virtual void save (Stream &stream) const
virtual void draw (Painter &painter) const
virtual void addToBBox (Rect &box, const Matrix &m, bool cp) const
virtual double distance (const Vector &v, const Matrix &m, double bound) const
virtual void snapVtx (const Vector &mouse, const Matrix &m, Vector &pos, double &bound) const
virtual void snapBnd (const Vector &mouse, const Matrix &m, Vector &pos, double &bound) const
- Public Member Functions inherited from ipe::SubPath
virtual ~SubPath ()=0
virtual bool closed () const
virtual const ClosedSplineasClosedSpline () const
virtual const CurveasCurve () const

Additional Inherited Members

- Public Types inherited from ipe::SubPath
enum  Type { ECurve, EEllipse, EClosedSpline }

Detailed Description

An ellipse subpath.

Constructor & Destructor Documentation

Ellipse::Ellipse ( const Matrix m)

Member Function Documentation

SubPath::Type Ellipse::type ( ) const
virtual

Return type of this subpath.

Implements ipe::SubPath.

const Ellipse * Ellipse::asEllipse ( ) const
virtual

Return this object as an Ellipse, or 0 if it's not an ellipse.

Reimplemented from ipe::SubPath.

Matrix ipe::Ellipse::matrix ( ) const
inline

Return matrix that transforms unit circle to the ellipse.

void Ellipse::save ( Stream stream) const
virtual

Save subpath to XML stream.

Implements ipe::SubPath.

void Ellipse::draw ( Painter painter) const
virtual

Draw subpath (does not call drawPath()).

Implements ipe::SubPath.

void Ellipse::addToBBox ( Rect box,
const Matrix m,
bool  cp 
) const
virtual

Add subpath to box.

Implements ipe::SubPath.

double Ellipse::distance ( const Vector v,
const Matrix m,
double  bound 
) const
virtual

Return distance from v to subpath transformed by m.

Implements ipe::SubPath.

void Ellipse::snapVtx ( const Vector mouse,
const Matrix m,
Vector pos,
double &  bound 
) const
virtual

snaps to center of ellipse.

Implements ipe::SubPath.

void Ellipse::snapBnd ( const Vector mouse,
const Matrix m,
Vector pos,
double &  bound 
) const
virtual

Snap to boundary of subpath.

Implements ipe::SubPath.


The documentation for this class was generated from the following files:
  • ipeshape.h
  • ipeshape.cpp

ipe-7.1.4/build/doc/classipe_1_1_bitmap_1_1_m_render_data-members.html0000644000175000017500000000517712120621776025455 0ustar otfriedotfried Ipelib: Member List
ipe::Bitmap::MRenderData Member List

This is the complete list of members for ipe::Bitmap::MRenderData, including all inherited members.

~MRenderData()ipe::Bitmap::MRenderDatavirtual

ipe-7.1.4/build/doc/classipe_1_1_transform_tool-members.html0000644000175000017500000002351212120621776023736 0ustar otfriedotfried Ipelib: Member List
ipe::TransformTool Member List

This is the complete list of members for ipe::TransformTool, including all inherited members.

compute(const Vector &v)ipe::TransformToolprotected
draw(Painter &painter) const ipe::TransformToolvirtual
ERotate enum valueipe::TransformTool
EScale enum valueipe::TransformTool
EStretch enum valueipe::TransformTool
ETranslate enum valueipe::TransformTool
iCanvasipe::Toolprotected
iMouseDownipe::TransformToolprotected
iOnlyHorizontalipe::TransformToolprotected
iOnlyVerticalipe::TransformToolprotected
iOriginipe::TransformToolprotected
iPageipe::TransformToolprotected
isValid() const ipe::TransformTool
iTransformipe::TransformToolprotected
iTypeipe::TransformToolprotected
iValidipe::TransformToolprotected
iViewipe::TransformToolprotected
iWithShiftipe::TransformToolprotected
key(int code, int modifiers, String text)ipe::Toolvirtual
mouseButton(int button, bool press)ipe::TransformToolvirtual
mouseMove()ipe::TransformToolvirtual
report()ipe::TransformToolvirtual
Tool(CanvasBase *canvas)ipe::Toolprotected
TransformTool(CanvasBase *canvas, Page *page, int view, TType type, bool withShift)ipe::TransformTool
TType enum nameipe::TransformTool
~Tool()ipe::Toolvirtual

ipe-7.1.4/build/doc/manual_19.html0000644000175000017500000000555512120621776016510 0ustar otfriedotfried Ipe Manual -- 4.4 Group objects
4.5 Reference objects and symbols4 Object types4.3 Image objects4.4 Group objects

4.4 Group objects

Group objects are created by selecting any number of objects and using the Group function from the Edit menu. The grouped objects then behave like a single object. To modify a group object, it has to be decomposed into its parts using Ungroup.

A clipping path can be added to a group object. The group will then be clipped to this path—nothing will be drawn outside the clipping path. To add a clipping path, select a group as the primary selection, and a path object as the secondary selection. Then select Add clipping path from the group's context menu.

ipe-7.1.4/build/doc/classipe_1_1_pdf_bool-members.html0000644000175000017500000001345512120621776022457 0ustar otfriedotfried Ipelib: Member List
ipe::PdfBool Member List

This is the complete list of members for ipe::PdfBool, including all inherited members.

array() const ipe::PdfObjvirtual
boolean() const ipe::PdfBoolvirtual
dict() const ipe::PdfObjvirtual
name() const ipe::PdfObjvirtual
null() const ipe::PdfObjvirtual
number() const ipe::PdfObjvirtual
PdfBool(bool val)ipe::PdfBoolinlineexplicit
ref() const ipe::PdfObjvirtual
repr() const ipe::PdfObj
string() const ipe::PdfObjvirtual
value() const ipe::PdfBoolinline
write(Stream &stream) const ipe::PdfBoolvirtual
~PdfObj()=0ipe::PdfObjpure virtual

ipe-7.1.4/build/doc/classipe_1_1_rect-members.html0000644000175000017500000002062512120621776021625 0ustar otfriedotfried Ipelib: Member List
ipe::Rect Member List

This is the complete list of members for ipe::Rect, including all inherited members.

addPoint(const Vector &rhs)ipe::Rect
addRect(const Rect &rhs)ipe::Rect
bottom() const ipe::Rectinline
bottomLeft() const ipe::Rectinline
bottomRight() const ipe::Rectinline
certainClearance(const Vector &v, double bound) const ipe::Rect
clear()ipe::Rectinline
clipTo(const Rect &rhs)ipe::Rect
contains(const Vector &rhs) const ipe::Rect
contains(const Rect &rhs) const ipe::Rect
height() const ipe::Rectinline
intersects(const Rect &rhs) const ipe::Rect
isEmpty() const ipe::Rectinline
left() const ipe::Rectinline
operator<<(Stream &stream, const Rect &rhs)ipe::Rectrelated
Rect()ipe::Rectinlineexplicit
Rect(const Vector &c)ipe::Rectinlineexplicit
Rect(const Vector &c1, const Vector &c2)ipe::Rectexplicit
right() const ipe::Rectinline
top() const ipe::Rectinline
topLeft() const ipe::Rectinline
topRight() const ipe::Rectinline
width() const ipe::Rectinline

ipe-7.1.4/build/doc/manual_38.html0000644000175000017500000001074212120621776016503 0ustar otfriedotfried Ipe Manual -- 8.4 Using Truetype fonts
8.5 Unicode text8 Advanced topics8.3 Troubleshooting the LaTeX-conversion8.4 Using Truetype fonts

8.4 Using Truetype fonts

To make PDF presentations that are as "fancy" as the PowerPoint presentations of competing speakers one needs to use fancy fonts. It's not hard to find nice fonts, but they are mostly in Truetype (TTF) format. This section explains how to use TTF fonts in Ipe.

Ipe relies on Pdflatex to translate the text source representation into a string of PDF operators and font subsets, that can then be used to generate Postscript, PDF, and to display the text on the screen. Ipe can therefore use any font that Pdflatex can handle, and to use a TTF font we just have to add it to Pdflatex's font reportoire.

I've made a webpage explaining the steps necessary to add a TTF font to Pdftex's font repertoire, using the lhandw.ttf font as an example. Let's assume that you have performed these steps, and that you can access the font when running Pdflatex normally (not from Ipe).

We are then ready to try the font from within Ipe. Let's first assume you only want to use the new font in a few places in your Ipe document. You should define a command analogous to \textrm to switch to the new font. Open the Document properties dialog in the Edit menu, and add this line to the Latex preamble:

\DeclareTextFontCommand{\textlh}
{\fontencoding{T1}\fontfamily{lhandw}\selectfont}
You can now use \textlh inside Ipe text objects to typeset in Lucida-Handwriting.

Finally, let's make a multi-page presentation typeset wholly using Lucida-Handwriting. This declaration in the Latex preamble will change the document fonts:

\renewcommand{\encodingdefault}{T1}
\renewcommand{\rmdefault}{lhandw}
\renewcommand{\sfdefault}{phv}
\renewcommand{\ttdefault}{pcr}
Note that this switches all text fonts to TTF or Postscript fonts. This is necessary, as we use the T1 encoding (an 8-bit encoding) for Lucida-Handwriting. Keeping Computer-Modern as the font for \textsf or \texttt would cause LaTeX to load the T1 version of Computer-Modern. These are bitmapped "Type3" fonts, which Ipe cannot handle.
ipe-7.1.4/build/doc/classipe_1_1_select_tool-members.html0000644000175000017500000001103712120621776023201 0ustar otfriedotfried Ipelib: Member List
ipe::SelectTool Member List

This is the complete list of members for ipe::SelectTool, including all inherited members.

draw(Painter &painter) const ipe::SelectToolvirtual
iCanvasipe::Toolprotected
key(int code, int modifiers, String text)ipe::SelectToolvirtual
mouseButton(int button, bool press)ipe::SelectToolvirtual
mouseMove()ipe::SelectToolvirtual
SelectTool(CanvasBase *canvas, Page *page, int view, double selectDistance, bool nonDestructive)ipe::SelectTool
Tool(CanvasBase *canvas)ipe::Toolprotected
~Tool()ipe::Toolvirtual

ipe-7.1.4/build/doc/tabs.css0000644000175000017500000000221312120621776015463 0ustar otfriedotfried.tabs, .tabs2, .tabs3 { background-image: url('tab_b.png'); width: 100%; z-index: 101; font-size: 13px; font-family: 'Lucida Grande',Geneva,Helvetica,Arial,sans-serif; } .tabs2 { font-size: 10px; } .tabs3 { font-size: 9px; } .tablist { margin: 0; padding: 0; display: table; } .tablist li { float: left; display: table-cell; background-image: url('tab_b.png'); line-height: 36px; list-style: none; } .tablist a { display: block; padding: 0 20px; font-weight: bold; background-image:url('tab_s.png'); background-repeat:no-repeat; background-position:right; color: #283A5D; text-shadow: 0px 1px 1px rgba(255, 255, 255, 0.9); text-decoration: none; outline: none; } .tabs3 .tablist a { padding: 0 10px; } .tablist a:hover { background-image: url('tab_h.png'); background-repeat:repeat-x; color: #fff; text-shadow: 0px 1px 1px rgba(0, 0, 0, 1.0); text-decoration: none; } .tablist li.current a { background-image: url('tab_a.png'); background-repeat:repeat-x; color: #fff; text-shadow: 0px 1px 1px rgba(0, 0, 0, 1.0); } ipe-7.1.4/build/doc/functions_0x73.html0000644000175000017500000007035112120621776017507 0ustar otfriedotfried Ipelib: Class Members
Here is a list of all class members with links to the classes they belong to:

- s -


ipe-7.1.4/build/doc/luageo.html0000644000175000017500000002062212120621776016166 0ustar otfriedotfried Ipelib: Lua bindings for geometric objects
Lua bindings for geometric objects

All Ipelib objects have constructors of the form:

 v = ipe.Vector()
 m = ipe.Matrix()
 m = ipe.Translation()  -- another Matrix constructor
 m = ipe.Rotation()     -- yet another Matrix constructor
 r = ipe.Rect()
 l = ipe.Line()
 l = ipe.LineThrough()  -- another Line constructor
 l = ipe.Bisector()     -- yet another Line constructor
 s = ipe.Segment()
 b = ipe.Bezier()
 a = ipe.Arc()

Note that ipe::Angle and ipe::Linear are not bound in Lua. Use numbers and ipe.Matrix instead. A useful method for angles is:

beta = ipe.normalizeAngle(alpha, lowLimit)

Vector

ipe.Vector binds ipe::Vector. There are the following methods:

v = ipe.Vector()         -- zero vector
v = ipe.Vector(x, y)
v = ipe.Direction(alpha) -- unit vector in this direction 
a = v.x                  -- read only access to x and y coordinates
b = v.y

v:len() -- returns norm of vector
v:sqLen() -- returns square of norm
v:normalized() -- returns this vector normalized
v:orthogonal() -- returns this vector rotated left by 90 degrees
v:factorize(u) -- factors v = lambda u + x, where x orth. to u, u is unit
v:angle()     -- return direction 
v == w        -- vector equality
v ~= w
-v            -- unary minus
v + w         -- vector addition
v - w         -- vector difference
5 * v         -- multiplication with a scalar
v * 5         -- multiplication with a scalar
v .. w        -- dot product

Matrix

ipe.Matrix binds ipe::Matrix. It has the following methods:

m = ipe.Matrix()                        -- identity matrix
m = ipe.Matrix(a1, a2, a3, a4)          -- linear transformation
m = ipe.Matrix(a1, a2, a3, a4, a5, a6)  -- affine transformation
m = ipe.Matrix( { a1, a2, a3, a4, a5, a6 } ) -- same from table
m = ipe.Rotation(alpha)                 -- rotation matrix
m = ipe.Translation(v)                  -- v is a vector
m = ipe.Translation(x, y)

m1 == m2          -- matrix equality
m1 * m2           -- matrix multiplication
m * v             -- matrix * vector
m * arc           -- matrix * arc

m:elements()      -- returns six-element array with elements

m:isIdentity()
m:isSingular()
m:inverse()
m:translation()   -- return translation component
m:linear()        -- returns matrix without the translation component

Rect

ipe.Rect binds ipe::Rect. This is the only mutable geometric object - take care not to be surprised when ipe.Rect objects are shared.

It has the following methods:

r = ipe.Rect()    -- empty
r:isEmpty()
r:topRight()
r:bottomLeft()
r:topLeft()
r:bottomRight()
r:left()
r:right()
r:bottom()
r:top()
r:width()
r:height()
r:add(v)          -- extend to cover vector v
r1:add(r2)        -- extend to cover rectangle r2
r1:clipTo(r2)     -- clip r1 to lie inside r2
r:contains(v)     
r1:contains(r2)
r1:intersects(r2)

Line

ipe.Line binds ipe::Line. It has the following methods:

l = ipe.Line(p, dir)      -- dir must be unit vector
l = ipe.LineThrough(p, q)
l = ipe.Bisector(p, q)

-- l:side() returns +1 if v lies to the left side of the line, 
-- 0 if on line, -1 if on the right side
l:side(v)                 
l:point()                 -- starting point of line
l:dir()                   -- unit direction vector
l:normal()                -- unit normal vector pointing to the left side
l:distance(v)             -- returns distance from point to line
l1:intersects(l2)         -- returns intersection point or nil
l:project(p)              -- projection of point on line

Segment

ipe.Segment binds ipe::Segment. It has the following methods:

s = ipe.Segment(p, q)   
p, q = s:endpoints()      -- returns both endpoints
s:line()                  -- returns an ipe.Line
s:project(p)              -- returns projection or nil
s:distance(p)
s:intersects(l)           -- return intersection point or nil
s1:intersects(s2)

Bezier

ipe.Bezier binds ipe::Bezier. It has the following methods:

b = ipe.Bezier(v1, v2, v3, v4)  
b:point(t)                -- point at value t
v1, v2, v3, v4 = b:controlpoints()  -- returns all four control points
b:bbox()
t, p = b:snap(pos)
b:intersects(s)           -- return intersection point or nil
b:intersects(l)

Arc

ipe.Arc binds ipe::Arc. It has the following methods:

a = ipe.Arc(m)            -- ellipse defined by ipe.Matrix m
a = ipe.Arc(m, p, q)      -- arc from p to q
a = ipe.Arc(m, alpha, beta)

a:endpoints()             -- returns two endpoints
a:angles()                -- returns two angles
a:bbox()
a:matrix()
a:isEllipse() 
alpha, p = a:snap(pos)
a:intersects(s)           -- return intersection point or nil
a:intersects(l)

ipe-7.1.4/build/doc/group__high.html0000644000175000017500000001600112120621776017200 0ustar otfriedotfried Ipelib: Ipe Utilities
Ipe Utilities

Classes

class  ipe::ObjectFactory
 Factory for Ipe leaf objects. More...
class  ipe::ImlParser
 XML Parser for Ipe documents and style sheets. More...
class  ipe::Visitor
 Base class for visitors to Object. More...
class  ipe::Snap
 Performs snapping operations, and stores snapping state. More...
class  ipe::BitmapFinder
 A visitor that recursively scans objects and collects all bitmaps. More...
class  ipe::BBoxPainter
 Paint objects using this painter to compute an accurate bounding box. More...
class  ipe::A85Stream
 Filter stream adding ASCII85 encoding. More...
class  ipe::Base64Stream
 Filter stream adding Base64 encoding. More...
class  ipe::A85Source
 Filter source adding ASCII85 decoding. More...
class  ipe::Base64Source
 Filter source adding Base64 decoding. More...
class  ipe::DeflateStream
 Filter stream adding flate compression. More...
class  ipe::InflateSource
 Filter source adding flate decompression. More...

Detailed Description

Classes to manage Ipe documents and objects.

This module contains classes used in the implementation of the Ipe program itself. The only classes from this module you may be interested in are Visitor (which is essential to traverse an Ipe object structure), and perhaps Snap (if you are writing an Ipelet whose behavior depends on the current snap setting in the Ipe program).


ipe-7.1.4/build/doc/sync_on.png0000644000175000017500000000151512120621776016202 0ustar otfriedotfried‰PNG  IHDRàw=øIDATxíÝ_HTYÀñï8ã¤ó§i§4-g6ÆËÕ&kQ)¨Ô!Š0ÒURKÚ…„ê¡/»PEÁ>ìK-+KÁ²Ñ.Y”¾dEPaA‰ø°¥¶›ZSÓïÜ;3wºŠ–¯—߯gfîïœsçœWKÇñ.€ÉøD­¨a‘'¬âq_ôˆk¢ÀŒ ÀDŽøQ´ÄïC¨¶åñÏÿgÅ ñ 0„Y‚:qZ¦Á)~õâ€èLý0HVñ× žz-¿‰C“%¨g¦˜6€é8%Úõ¬ëwêÙUÏ¿˜ª³Ä }? ?€·3ÀÀž©Š À”K• @hà a±ðaÇæUe‹ sù~ë2²ì“&Ú&B*AÄljæºììi*˨,Ëçí»÷oÆ£T”,d[˜¼3-*ÁÀ…>å‡Ë çLÉŸçfk˜Ò éw#*AEjKUy>ûšËÉõ&{µ¢8—m5Ki¬ jjƒD*¿NŽÖigwÃ7Dª’mz骹úKÛ¾±ˆ¶M!æ¤ÍkÐ?šoý¬_åÓlXí#Ò~–¸¬ê×ÒÑXŠÓ‘ùRÙ*Eû‚ՂדðEÜ;6«e"Q(²Ù=–¿Ezæ5Kؼָ_ 1òzBªJë ±XŒì96åªjL^7{ùãJÑ÷1½i@%8'7M©_\Qœ#ÓUŒËñýÿyõ Wo Éx8¼s¥v¯ªì|×SnÜ q_m Ýé î>bèÕí[JX,½4[Tú{R£ë¼ôˆ¾þa€tÝjjzzÅ'ÅìȶiIžŽòwÏs ¡€—ÕKøõâC^ŽŒ˜Y­¨µÉ%6¨´êˆº]vÛðhâ½iWv–hôëê°Ò¨¾'æÌ‚·ñ|[ßìúÅ^€YrD=<ýDû]äÇ÷s€Ïõ‹8™ºCì? À ¨—t4õᩎ¡Jã‡W‹É± îr¼cjMɘìx| šE©øNÔ‰œøA¢þ«–€Z¼ñ‡jó î#™§¢¢4gIEND®B`‚ipe-7.1.4/build/doc/classipe_1_1_lex.html0000644000175000017500000004106212120621776020026 0ustar otfriedotfried Ipelib: ipe::Lex Class Reference

#include <ipebase.h>

Public Member Functions

 Lex (String str)
String token ()
String nextToken ()
int getInt ()
int getHexByte ()
Fixed getFixed ()
unsigned long int getHexNumber ()
double getDouble ()
char getChar ()
void skipWhitespace ()
Lexoperator>> (int &i)
Lexoperator>> (double &d)
Lexoperator>> (Fixed &d)
void mark ()
void fromMark ()
bool eos () const

Detailed Description

Lexical analyser. Seeded with a string.

Constructor & Destructor Documentation

Lex::Lex ( String  str)
explicit

Construct lexical analyzer from a string.

Member Function Documentation

String Lex::token ( )

Return NextToken, but without extracting it.

String Lex::nextToken ( )

Extract next token.

Skips any whitespace before the token. Returns empty string if end of string is reached.

int Lex::getInt ( )

Extract integer token (skipping whitespace).

int Lex::getHexByte ( )

Extract byte in hex (skipping whitespace).

Fixed Lex::getFixed ( )

Extract Fixed token (skipping whitespace).

unsigned long int Lex::getHexNumber ( )

Extract hexadecimal token (skipping whitespace).

double Lex::getDouble ( )

Extract double token (skipping whitespace).

char ipe::Lex::getChar ( )
inline

Extract next character (not skipping anything).

void Lex::skipWhitespace ( )

Skip over whitespace.

Lex& ipe::Lex::operator>> ( int &  i)
inline

Operator syntax for getInt().

Lex& ipe::Lex::operator>> ( double &  d)
inline

Operator syntax for getDouble().

Lex& ipe::Lex::operator>> ( Fixed d)
inline

Operator syntax for getFixed().

void ipe::Lex::mark ( )
inline

Mark the current position.

void ipe::Lex::fromMark ( )
inline

Reset reader to the marked position.

bool ipe::Lex::eos ( ) const
inline

Return true if at end of string (not even whitespace left).


The documentation for this class was generated from the following files:
  • ipebase.h
  • ipebase.cpp

ipe-7.1.4/build/doc/manual_40.html0000644000175000017500000000742312120621776016476 0ustar otfriedotfried Ipe Manual -- 8.6 Customizing Ipe
8 Advanced topics8.5 Unicode text8.6 Customizing Ipe

8.6 Customizing Ipe

Since most of Ipe is writing in Lua, an interpreted language, much of Ipe's behavior can be changed without recompilation.

The main customization options are in the files prefs.lua (general settings), shortcuts.lua (keyboard shortcuts), and mouse.lua (mouse shortcuts). (Check the Lua code path in Show configuration in the Help menu if you can't locate the files.)

If you have installed Ipe for your personal use only (for instance under Windows), you can simply modify the original Lua file. In all other cases, you need to provide a small Lua ipelet that will change the setting you wish to change.

A small example is the following ipelet that changes a keyboard shortcut and the maximum zoom:

----------------------------------------------------------------------
-- My customization ipelet: customize.lua
----------------------------------------------------------------------
prefs.max_zoom = 100
shortcuts.insert_text_box = "I",
shortcuts.mode_splines = "Alt+Ctrl+I"

You can use keyboard shortcuts consisting of more than one key, such as Ctrl+X,Ctrl+C. Use commas to separate the key presses—up to four are supported.

The ipelet needs to be placed with the extension .lua somewhere on the ipelet path (check Show configuration again). On Unix, the directory $HOME/.ipe/ipelets will do nicely. On Windows, you will have to set the environment variable IPELETPATH.

ipe-7.1.4/build/doc/group__doc.html0000644000175000017500000000707312120621776017037 0ustar otfriedotfried Ipelib: Ipe Document
Ipe Document

Classes

class  ipe::Document
 The model for an Ipe document. More...
class  ipe::Page
 An Ipe document page. More...
class  ipe::StyleSheet
 A style sheet maps symbolic names to absolute values. More...
class  ipe::Cascade
 A cascade of style sheets. More...

Detailed Description

The classes managing an Ipe document.

The main class, Document, represents an entire Ipe document, and allows you to load, save, access, and modify such a document.

Other classes represent pages, layers, and views of a document. Another important class is the StyleSheet, which maps symbolic attributes to absolute values.


ipe-7.1.4/build/doc/manual_1.html0000644000175000017500000001157212120621776016413 0ustar otfriedotfried Ipe Manual -- 1 Introduction
2 About Ipe filesTop1 Introduction

1 Introduction

Preparing figures for a scientific article is a time-consuming process. If you are using the LaTeX document preparation system in an environment where you can include (encapsulated) Postscript figures or PDF figures, then the extensible drawing editor Ipe may be able to help you in the task. Ipe allows you to prepare and edit drawings containing a variety of basic geometry primitives like lines, splines, polygons, circles etc.

Ipe also allows you to add text to your drawings, and unlike most other drawing programs, Ipe treats these text object as LaTeX text. This has the advantage that all usual LaTeX commands can be used within the drawing, which makes the inclusion of mathematical formulae (or even simple labels like "qi") much simpler. Ipe processes your LaTeX source and includes its Postscript or PDF rendering in the figure.

In addition, Ipe offers you some editing functions that can usually only be found in professional drawing programs or cad systems. For instance, it incorporates a context sensitive snapping mechanism, which allows you to draw objects meeting in a point, having parallel edges, objects aligned on intersection points of other objects, rectilinear and c-oriented objects and the like. Whenever one of the snapping modes is enabled, Ipe shows you Fifi, a secondary cursor, which keeps track of the current aligning.

One of the nicest features of Ipe is the fact that it is extensible. You can write your own functions, so-called ipelets. Once registered with Ipe by adding them to your ipelet path, you can use those functions like Ipe's own editing functions. (In fact, some of the functions in the standard Ipe distribution are actually implemented as ipelets.) Ipelets can be written in Lua, an easy-to-learn interpreted language that is embedded into Ipe, or also in C++. Among others, there is an ipelet to compute Voronoi diagrams.

Making a presentation is another task that requires drawing figures. You can use Ipe to prepare presentations in PDF format. Ipe offers many features to make attractive presentations.

Ipe tries to be self-explanatory. There is online help available, and most commands tell you about options, shortcuts, or errors. Nevertheless, it would probably be wise to read at least a few sections of this manual. If you have used Ipe 6 before, you should definitely have a look at what has changed. If you have never used Ipe before, then the chapter on general concepts and the chapter explaining the snapping functions would be a useful read. If you want to use Ipe to prepare presentations, you should also read the chapter on presentations.

ipe-7.1.4/build/doc/dynsections.js0000644000175000017500000000413412120621776016724 0ustar otfriedotfriedfunction toggleVisibility(linkObj) { var base = $(linkObj).attr('id'); var summary = $('#'+base+'-summary'); var content = $('#'+base+'-content'); var trigger = $('#'+base+'-trigger'); var src=$(trigger).attr('src'); if (content.is(':visible')===true) { content.hide(); summary.show(); $(linkObj).addClass('closed').removeClass('opened'); $(trigger).attr('src',src.substring(0,src.length-8)+'closed.png'); } else { content.show(); summary.hide(); $(linkObj).removeClass('closed').addClass('opened'); $(trigger).attr('src',src.substring(0,src.length-10)+'open.png'); } return false; } function updateStripes() { $('table.directory tr'). removeClass('even').filter(':visible:even').addClass('even'); } function toggleLevel(level) { $('table.directory tr').each(function(){ var l = this.id.split('_').length-1; var i = $('#img'+this.id.substring(3)); var a = $('#arr'+this.id.substring(3)); if (l Ipelib: Member List
ipe::PsPainter Member List

This is the complete list of members for ipe::PsPainter, including all inherited members.

addClipPath()ipe::Painter
cascade() const ipe::Painterinline
closePath()ipe::Painter
curveTo(const Vector &v1, const Vector &v2, const Vector &v3)ipe::Painter
curveTo(const Bezier &bezier)ipe::Painterinline
dashStyle() const ipe::Painterinline
dashStyle(std::vector< double > &dashes, double &offset) const ipe::Painter
doAddClipPath()ipe::PsPainterprotectedvirtual
doClosePath()ipe::PdfPainterprotectedvirtual
doCurveTo(const Vector &v1, const Vector &v2, const Vector &v3)ipe::PdfPainterprotectedvirtual
doDrawArc(const Arc &arc)ipe::Painterprotectedvirtual
doDrawBitmap(Bitmap bitmap)ipe::PsPainterprotectedvirtual
doDrawPath(TPathMode mode)ipe::PsPainterprotectedvirtual
doDrawSymbol(Attribute symbol)ipe::PdfPainterprotectedvirtual
doDrawText(const Text *text)ipe::PdfPainterprotectedvirtual
doLineTo(const Vector &v)ipe::PdfPainterprotectedvirtual
doMoveTo(const Vector &v)ipe::PdfPainterprotectedvirtual
doNewPath()ipe::PsPainterprotectedvirtual
doPop()ipe::PdfPainterprotectedvirtual
doPush()ipe::PdfPainterprotectedvirtual
drawArc(const Arc &arc)ipe::Painter
drawArcAsBezier(double alpha)ipe::Painterprotected
drawAttributes()ipe::PdfPainterprotected
drawBitmap(Bitmap bitmap)ipe::Painter
drawColor(Stream &stream, Color color, const char *gray, const char *rgb)ipe::PdfPainterstatic
drawEllipse()ipe::Painter
drawOpacity()ipe::PdfPainterprotected
drawPath(TPathMode mode)ipe::Painter
drawSymbol(Attribute symbol)ipe::Painter
drawText(const Text *text)ipe::Painter
fill() const ipe::Painterinline
fillRule() const ipe::Painterinline
gradient() const ipe::Painterinline
iActiveStateipe::PdfPainterprotected
iCascadeipe::Painterprotected
iInPathipe::Painterprotected
iMatrixipe::Painterprotected
iStateipe::Painterprotected
iStreamipe::PdfPainterprotected
lineCap() const ipe::Painterinline
lineJoin() const ipe::Painterinline
lineTo(const Vector &v)ipe::Painter
matrix() const ipe::Painterinline
moveTo(const Vector &v)ipe::Painter
newPath()ipe::Painter
opacity() const ipe::Painterinline
Painter(const Cascade *style)ipe::Painter
PdfPainter(const Cascade *style, Stream &stream)ipe::PdfPainter
pen() const ipe::Painterinline
pop()ipe::Painter
popMatrix()ipe::Painter
PsPainter(const Cascade *style, Stream &stream)ipe::PsPainter
push()ipe::Painter
pushMatrix()ipe::Painter
rect(const Rect &re)ipe::Painter
setDashStyle(Attribute dash)ipe::Painter
setFill(Attribute color)ipe::Painter
setFillRule(TFillRule rule)ipe::Painter
setGradient(Attribute grad)ipe::Painter
setLineCap(TLineCap cap)ipe::Painter
setLineJoin(TLineJoin join)ipe::Painter
setOpacity(Attribute opaq)ipe::Painter
setPen(Attribute pen)ipe::Painter
setStroke(Attribute color)ipe::Painter
setSymFill(Attribute color)ipe::Painter
setSymPen(Attribute wid)ipe::Painter
setSymStroke(Attribute color)ipe::Painter
setTiling(Attribute til)ipe::Painter
stroke() const ipe::Painterinline
symFill() const ipe::Painterinline
symPen() const ipe::Painterinline
symStroke() const ipe::Painterinline
tiling() const ipe::Painterinline
transform(const Matrix &m)ipe::Painter
translate(const Vector &v)ipe::Painter
untransform(TTransformations trans)ipe::Painter
~Painter()ipe::Paintervirtual
~PdfPainter()ipe::PdfPainterinlinevirtual
~PsPainter()ipe::PsPainter

ipe-7.1.4/build/doc/manual_15.html0000644000175000017500000000644012120621776016476 0ustar otfriedotfried Ipe Manual -- 4 Object types
5 SnappingTop3 General Concepts4 Object types

4 Object types

Ipe supports five different types of objects that can be placed on a page, namely path objects (which includes all objects with a stroked contour and filled interior, such as (poly)lines, polygons, splines, splinegons, circles and ellipses, circular and elliptic arcs, and rectangles), text objects, image objects, group objects, and reference objects (which means that a symbol is used at a certain spot on the page).

Path and text objects are created by clicking the left mouse button somewhere on the canvas using the correct Ipe mode. Group objects are created using the Group function in the Edit menu. Image objects are added to the document using the Insert image ipelet. Reference objects can be created either using mark mode, or using the Symbols ipelet.

ipe-7.1.4/build/doc/manual_3.html0000644000175000017500000001047112120621776016412 0ustar otfriedotfried Ipe Manual -- 3 General Concepts
4 Object typesTop2 About Ipe files3 General Concepts

3 General Concepts

After you start up Ipe, you will see a window with a large gray area containing a white rectangle. This area, the canvas, is the drawing area where you will create your figures. The white rectangle is your "sheet of paper", the first page of your document. (While Ipe doesn't stop you from drawing outside the paper, such documents generally do not print very well.)

At the top of the window, above the canvas, you find two toolbars: one for snapping modes, grid size and angular resolution; and another one to select the current mode.

On the left hand side of the canvas you find an area where you can select object properties such as stroke and fill color, pen width, path properties, text size, and mark size. Below it is a list of the layers of the current page.

All user interface elements have tool tips—if you move the mouse over them and wait a few seconds, a short explanation will appear. The mode toolbar allows you to set the current Ipe mode. Roughly speaking, the mode determines what the left mouse button will do when you click it in the figure. The leftmost five buttons select modes for selecting and transforming objects, the remaining buttons select modes for creating new objects.

Pressing the right mouse button pops up the object context menu in any mode.

In this chapter we will discuss the general concepts of Ipe. Understanding these properly will be essential if you want to get the most out of Ipe.

ipe-7.1.4/build/doc/classipe_1_1_file_stream-members.html0000644000175000017500000001452112120621776023160 0ustar otfriedotfried Ipelib: Member List
ipe::FileStream Member List

This is the complete list of members for ipe::FileStream, including all inherited members.

close()ipe::Streamvirtual
FileStream(std::FILE *file)ipe::FileStream
operator<<(char ch)ipe::Streaminline
operator<<(const String &s)ipe::Streaminline
operator<<(const char *s)ipe::Streaminline
operator<<(int i)ipe::Stream
operator<<(double d)ipe::Stream
putChar(char ch)ipe::FileStreamvirtual
putCString(const char *s)ipe::FileStreamvirtual
putHexByte(char b)ipe::Stream
putRaw(const char *data, int size)ipe::FileStreamvirtual
putString(String s)ipe::FileStreamvirtual
putXmlString(String s)ipe::Stream
tell() const ipe::FileStreamvirtual
~Stream()ipe::Streamvirtual

ipe-7.1.4/build/doc/classipe_1_1_pdf_bool.html0000644000175000017500000002457312120621776021032 0ustar otfriedotfried Ipelib: ipe::PdfBool Class Reference
ipe::PdfBool Class Reference

#include <ipepdfparser.h>

Inherits ipe::PdfObj.

Public Member Functions

 PdfBool (bool val)
virtual const PdfBoolboolean () const
virtual void write (Stream &stream) const
bool value () const
- Public Member Functions inherited from ipe::PdfObj
virtual ~PdfObj ()=0
virtual const PdfNullnull () const
virtual const PdfNumbernumber () const
virtual const PdfStringstring () const
virtual const PdfNamename () const
virtual const PdfRefref () const
virtual const PdfArrayarray () const
virtual const PdfDictdict () const
String repr () const

Detailed Description

The PDF bool object.

Constructor & Destructor Documentation

ipe::PdfBool::PdfBool ( bool  val)
inlineexplicit

Member Function Documentation

const PdfBool * PdfBool::boolean ( ) const
virtual

Return this object as PDF bool object.

Reimplemented from ipe::PdfObj.

void PdfBool::write ( Stream stream) const
virtual

Implements ipe::PdfObj.

bool ipe::PdfBool::value ( ) const
inline

The documentation for this class was generated from the following files:
  • ipepdfparser.h
  • ipepdfparser.cpp

ipe-7.1.4/build/doc/classipe_1_1_ellipse-members.html0000644000175000017500000001670612120621776022332 0ustar otfriedotfried Ipelib: Member List
ipe::Ellipse Member List

This is the complete list of members for ipe::Ellipse, including all inherited members.

addToBBox(Rect &box, const Matrix &m, bool cp) const ipe::Ellipsevirtual
asClosedSpline() const ipe::SubPathvirtual
asCurve() const ipe::SubPathvirtual
asEllipse() const ipe::Ellipsevirtual
closed() const ipe::SubPathvirtual
distance(const Vector &v, const Matrix &m, double bound) const ipe::Ellipsevirtual
draw(Painter &painter) const ipe::Ellipsevirtual
EClosedSpline enum valueipe::SubPath
ECurve enum valueipe::SubPath
EEllipse enum valueipe::SubPath
Ellipse(const Matrix &m)ipe::Ellipse
matrix() const ipe::Ellipseinline
save(Stream &stream) const ipe::Ellipsevirtual
snapBnd(const Vector &mouse, const Matrix &m, Vector &pos, double &bound) const ipe::Ellipsevirtual
snapVtx(const Vector &mouse, const Matrix &m, Vector &pos, double &bound) const ipe::Ellipsevirtual
type() const ipe::Ellipsevirtual
Type enum nameipe::SubPath
~SubPath()=0ipe::SubPathpure virtual

ipe-7.1.4/build/doc/classipe_1_1_b_box_painter-members.html0000644000175000017500000005427612120621776023514 0ustar otfriedotfried Ipelib: Member List
ipe::BBoxPainter Member List

This is the complete list of members for ipe::BBoxPainter, including all inherited members.

addClipPath()ipe::Painter
bbox() const ipe::BBoxPainterinline
BBoxPainter(const Cascade *style)ipe::BBoxPainter
cascade() const ipe::Painterinline
closePath()ipe::Painter
curveTo(const Vector &v1, const Vector &v2, const Vector &v3)ipe::Painter
curveTo(const Bezier &bezier)ipe::Painterinline
dashStyle() const ipe::Painterinline
dashStyle(std::vector< double > &dashes, double &offset) const ipe::Painter
doAddClipPath()ipe::BBoxPainterprotectedvirtual
doClosePath()ipe::Painterprotectedvirtual
doCurveTo(const Vector &v1, const Vector &v2, const Vector &v3)ipe::BBoxPainterprotectedvirtual
doDrawArc(const Arc &arc)ipe::Painterprotectedvirtual
doDrawBitmap(Bitmap bitmap)ipe::BBoxPainterprotectedvirtual
doDrawPath(TPathMode mode)ipe::BBoxPainterprotectedvirtual
doDrawSymbol(Attribute symbol)ipe::Painterprotectedvirtual
doDrawText(const Text *text)ipe::BBoxPainterprotectedvirtual
doLineTo(const Vector &v)ipe::BBoxPainterprotectedvirtual
doMoveTo(const Vector &v)ipe::BBoxPainterprotectedvirtual
doNewPath()ipe::BBoxPainterprotectedvirtual
doPop()ipe::BBoxPainterprotectedvirtual
doPush()ipe::BBoxPainterprotectedvirtual
drawArc(const Arc &arc)ipe::Painter
drawArcAsBezier(double alpha)ipe::Painterprotected
drawBitmap(Bitmap bitmap)ipe::Painter
drawEllipse()ipe::Painter
drawPath(TPathMode mode)ipe::Painter
drawSymbol(Attribute symbol)ipe::Painter
drawText(const Text *text)ipe::Painter
fill() const ipe::Painterinline
fillRule() const ipe::Painterinline
gradient() const ipe::Painterinline
iCascadeipe::Painterprotected
iInPathipe::Painterprotected
iMatrixipe::Painterprotected
iStateipe::Painterprotected
lineCap() const ipe::Painterinline
lineJoin() const ipe::Painterinline
lineTo(const Vector &v)ipe::Painter
matrix() const ipe::Painterinline
moveTo(const Vector &v)ipe::Painter
newPath()ipe::Painter
opacity() const ipe::Painterinline
Painter(const Cascade *style)ipe::Painter
pen() const ipe::Painterinline
pop()ipe::Painter
popMatrix()ipe::Painter
push()ipe::Painter
pushMatrix()ipe::Painter
rect(const Rect &re)ipe::Painter
setDashStyle(Attribute dash)ipe::Painter
setFill(Attribute color)ipe::Painter
setFillRule(TFillRule rule)ipe::Painter
setGradient(Attribute grad)ipe::Painter
setLineCap(TLineCap cap)ipe::Painter
setLineJoin(TLineJoin join)ipe::Painter
setOpacity(Attribute opaq)ipe::Painter
setPen(Attribute pen)ipe::Painter
setStroke(Attribute color)ipe::Painter
setSymFill(Attribute color)ipe::Painter
setSymPen(Attribute wid)ipe::Painter
setSymStroke(Attribute color)ipe::Painter
setTiling(Attribute til)ipe::Painter
stroke() const ipe::Painterinline
symFill() const ipe::Painterinline
symPen() const ipe::Painterinline
symStroke() const ipe::Painterinline
tiling() const ipe::Painterinline
transform(const Matrix &m)ipe::Painter
translate(const Vector &v)ipe::Painter
untransform(TTransformations trans)ipe::Painter
~Painter()ipe::Paintervirtual

ipe-7.1.4/build/doc/classipe_1_1_base64_stream-members.html0000644000175000017500000001405112120621776023323 0ustar otfriedotfried Ipelib: Member List
ipe::Base64Stream Member List

This is the complete list of members for ipe::Base64Stream, including all inherited members.

Base64Stream(Stream &stream)ipe::Base64Stream
close()ipe::Base64Streamvirtual
operator<<(char ch)ipe::Streaminline
operator<<(const String &s)ipe::Streaminline
operator<<(const char *s)ipe::Streaminline
operator<<(int i)ipe::Stream
operator<<(double d)ipe::Stream
putChar(char ch)ipe::Base64Streamvirtual
putCString(const char *s)ipe::Streamvirtual
putHexByte(char b)ipe::Stream
putRaw(const char *data, int size)ipe::Streamvirtual
putString(String s)ipe::Streamvirtual
putXmlString(String s)ipe::Stream
~Stream()ipe::Streamvirtual

ipe-7.1.4/build/doc/classipe_1_1_pdf_parser.html0000644000175000017500000002477312120621776021375 0ustar otfriedotfried Ipelib: ipe::PdfParser Class Reference
ipe::PdfParser Class Reference

#include <ipepdfparser.h>

Public Member Functions

 PdfParser (DataSource &source)
void getChar ()
bool eos () const
PdfToken token () const
void getToken ()
PdfObjgetObject ()
PdfObjgetObjectDef ()
PdfDictgetTrailer ()
void skipXRef ()

Detailed Description

PDF parser.

The parser understands the syntax of PDF files, but very little of its semantics. It is meant to be able to parse PDF documents created by Ipe for loading, and to extract information from PDF files created by Pdflatex.

The parser reads a PDF file sequentially from front to back, ignores the contents of 'xref' sections, stores only generation 0 objects, and stops after reading the first 'trailer' section (so it cannot deal with files with incremental updates). It cannot handle stream objects whose /Length entry has been deferred (using an indirect object).

Constructor & Destructor Documentation

PdfParser::PdfParser ( DataSource source)

Construct with a data source.

Member Function Documentation

void ipe::PdfParser::getChar ( )
inline
bool ipe::PdfParser::eos ( ) const
inline
PdfToken ipe::PdfParser::token ( ) const
inline
void PdfParser::getToken ( )

Read the next token from the input stream.

PdfObj * PdfParser::getObject ( )

Read one object from input stream.

PdfObj * PdfParser::getObjectDef ( )

Parse an object definition (current token is object number).

PdfDict * PdfParser::getTrailer ( )

Parse trailer dictionary (current token is 'trailer')

void PdfParser::skipXRef ( )

Skip xref table (current token is 'xref')


The documentation for this class was generated from the following files:
  • ipepdfparser.h
  • ipepdfparser.cpp

ipe-7.1.4/build/doc/fontbbox2.svg0000644000175000017500000002307012120621776016450 0ustar otfriedotfried ipe-7.1.4/build/doc/manual_33.html0000644000175000017500000001073212120621776016475 0ustar otfriedotfried Ipe Manual -- 7.5 Ipe symbols used from text objects
7 Presentations7.4 Gradient patterns7.5 Ipe symbols used from text objects

7.5 Ipe symbols used from text objects

Presentations often make use of itemize environments. You can make these prettier in a number of ways:

You can color your bullets:

<preamble>
\def\labelitemi{\LARGE\textcolor{red}{$\bullet$}}
</preamble>

Enumeration numbers could be put in a colored box:

<preamble>
\newcommand{\labelenumi}{\fbox{\Roman{enumi}}}
</preamble>

You could use the Dingbats font for nice enumerations, for instance by putting \usepackage{pifont} in your preamble, and then having text objects with \begin{dinglist}{43} or \begin{dingautolist}{172} (or use 182, 192, 202 for various circled numbers).

You can mark items as "good" and "bad" using these "bullets":

Bad item: \textcolor{red}{\ding{55}}
Good item: \textcolor{green}{\ding{52}}

Finally, you can custom design your own bullets by creating an Ipe symbol for it. For instance:

<symbol name="bullet(sfpx)">
  <path matrix="2 0 0 2 0 0" pen="sym-pen" stroke="sym-stroke" fill="sym-fill">
    0 0 m -1.0 0.333 l -0.8 0 l -1.0 -0.333 l h</path>
</symbol>
<preamble>
  \def\labelitemi{\raisebox{0.5ex}{\hbox to 0.3em%
      {\ipesymbol{bullet(sfpx)}{blue}{yellow}{normal}}}}
</preamble>

Note the use of the \ipesymbol{name}{stroke}{fill}{pen} command. It allows you to use an Ipe symbol from inside a text object. The symbol is magnified proportionally to the ex-height of the current font at the position where it is used. (And so the symbol should be designed to be the correct size for a font of ex-height 1pt.)

In the following example, we redefine the bullet to be a blue glassy sphere:

<gradient name="ball" type="radial" coords="-4 10 2 0 0 18">
  <stop offset="0" color="1 1 1"/>
  <stop offset="1" color="0 0 1"/>
</gradient>
<symbol name="sphere">
  <path matrix="0.04 0 0 0.04 0 0" fill="blue" gradient="ball">
    18 0 0 18 0 0 e
  </path>
</symbol>
<preamble>
  \def\labelitemi{\raisebox{0.5ex}{\hbox to 0.3em{\ipesymbol{sphere}{}{}{}}}}
</preamble>
ipe-7.1.4/build/doc/classipe_1_1_cascade-members.html0000644000175000017500000002223712120621776022254 0ustar otfriedotfried Ipelib: Member List
ipe::Cascade Member List

This is the complete list of members for ipe::Cascade, including all inherited members.

allCMaps(std::vector< String > &seq) const ipe::Cascade
allNames(Kind kind, AttributeSeq &seq) const ipe::Cascade
Cascade()ipe::Cascade
Cascade(const Cascade &rhs)ipe::Cascade
count() const ipe::Cascadeinline
fillRule() const ipe::Cascade
find(Kind, Attribute sym) const ipe::Cascade
findDefinition(Kind kind, Attribute sym) const ipe::Cascade
findEffect(Attribute sym) const ipe::Cascade
findEncoding() const ipe::Cascade
findGradient(Attribute sym) const ipe::Cascade
findLayout() const ipe::Cascade
findPageNumberStyle() const ipe::Cascade
findPreamble() const ipe::Cascade
findSymbol(Attribute sym) const ipe::Cascade
findTextPadding() const ipe::Cascade
findTiling(Attribute sym) const ipe::Cascade
findTitleStyle() const ipe::Cascade
has(Kind kind, Attribute sym) const ipe::Cascade
insert(int index, StyleSheet *sheet)ipe::Cascade
lineCap() const ipe::Cascade
lineJoin() const ipe::Cascade
operator=(const Cascade &rhs)ipe::Cascade
remove(int index)ipe::Cascade
saveAsXml(Stream &stream) const ipe::Cascade
sheet(int index)ipe::Cascadeinline
~Cascade()ipe::Cascade

ipe-7.1.4/build/doc/manual_5.html0000644000175000017500000001226112120621776016413 0ustar otfriedotfried Ipe Manual -- 3.2 The current selection
3.3 Moving and scaling objects3 General Concepts3.1 Order of objects3.2 The current selection

3.2 The current selection

Whenever you call an Ipe function, you have to specify which objects the function should operate on. This is done by selecting objects. The selected objects (the selection) consists of two parts: the primary selection consists of exactly one object (of course, this object could be a group). All additional selected objects form the secondary selection. Some functions (like the context menu) operate only on the primary selection, while others treat primary and secondary selections differently (the align functions, for instance, align the secondary selections with respect to the primary selection.)

The selection is shown by outlining the selected object in color. Note that the primary selection is shown with a slightly different look.

The primary and secondary selections can be set in selection mode. Clicking the left mouse button close to an object makes that object the primary selection and deselects all other objects. If you keep the Shift key pressed while clicking with the left mouse key, the object closest to the mouse will be added to or deleted from the current selection. You can also drag a rectangle with the mouse—when you release the mouse button, all objects inside the rectangle will be selected. With the Shift key, the selection status of all objects inside the rectangle will be switched.

To make it easier to select objects that are below or close to other objects, it is convenient to understand exactly how selecting objects works. In fact, when you press the mouse button, a list of all objects is computed that are sufficiently close to the mouse position (the exact distance is set as the select_distance in prefs.lua). This list is then sorted by increasing distance from the mouse and by increasing depth in the drawing. If Shift was not pressed, the current selection is now cleared. Then the first object in the list is presented. Now, while still keeping the mouse button pressed, you can use the Space key to step through the list of objects near the mouse in order of increasing depth and distance. When you release the right mouse button, the object is selected (or deselected).

When measuring the distance from the mouse position to objects, Ipe considers the boundary of objects only. So to select a filled object, don't just click somewhere in its interior, but close to its boundary.

Another way to select objects is using the Select all function from the Edit menu. It selects all objects on the page. Similarly, the Select all in layer function in the Layer menu selects all objects in the active layer.

ipe-7.1.4/build/doc/fontbbox.svg0000644000175000017500000002221612120621776016367 0ustar otfriedotfried ipe-7.1.4/build/doc/classipe_1_1_ps_painter.html0000644000175000017500000011046612120621776021407 0ustar otfriedotfried Ipelib: ipe::PsPainter Class Reference

#include <ipepswriter.h>

Inherits ipe::PdfPainter.

Public Member Functions

 PsPainter (const Cascade *style, Stream &stream)
 ~PsPainter ()
- Public Member Functions inherited from ipe::PdfPainter
 PdfPainter (const Cascade *style, Stream &stream)
virtual ~PdfPainter ()
- Public Member Functions inherited from ipe::Painter
 Painter (const Cascade *style)
virtual ~Painter ()
void transform (const Matrix &m)
void untransform (TTransformations trans)
void translate (const Vector &v)
void push ()
void pop ()
void pushMatrix ()
void popMatrix ()
void newPath ()
void moveTo (const Vector &v)
void lineTo (const Vector &v)
void curveTo (const Vector &v1, const Vector &v2, const Vector &v3)
void curveTo (const Bezier &bezier)
void rect (const Rect &re)
void drawEllipse ()
void drawArc (const Arc &arc)
void closePath ()
void drawPath (TPathMode mode)
void drawBitmap (Bitmap bitmap)
void drawText (const Text *text)
void drawSymbol (Attribute symbol)
void addClipPath ()
void setStroke (Attribute color)
void setFill (Attribute color)
void setPen (Attribute pen)
void setDashStyle (Attribute dash)
void setLineCap (TLineCap cap)
void setLineJoin (TLineJoin join)
void setFillRule (TFillRule rule)
void setSymStroke (Attribute color)
void setSymFill (Attribute color)
void setSymPen (Attribute wid)
void setOpacity (Attribute opaq)
void setTiling (Attribute til)
void setGradient (Attribute grad)
const Cascadecascade () const
Color stroke () const
Color fill () const
const Matrixmatrix () const
Fixed pen () const
String dashStyle () const
void dashStyle (std::vector< double > &dashes, double &offset) const
TLineCap lineCap () const
TLineJoin lineJoin () const
TFillRule fillRule () const
Color symStroke () const
Color symFill () const
Fixed symPen () const
Fixed opacity () const
Attribute tiling () const
Attribute gradient () const

Protected Member Functions

virtual void doNewPath ()
virtual void doDrawPath (TPathMode mode)
virtual void doDrawBitmap (Bitmap bitmap)
virtual void doAddClipPath ()
- Protected Member Functions inherited from ipe::PdfPainter
virtual void doPush ()
virtual void doPop ()
virtual void doMoveTo (const Vector &v)
virtual void doLineTo (const Vector &v)
virtual void doCurveTo (const Vector &v1, const Vector &v2, const Vector &v3)
virtual void doClosePath ()
virtual void doDrawText (const Text *text)
virtual void doDrawSymbol (Attribute symbol)
void drawAttributes ()
void drawOpacity ()
- Protected Member Functions inherited from ipe::Painter
virtual void doDrawArc (const Arc &arc)
void drawArcAsBezier (double alpha)

Additional Inherited Members

- Static Public Member Functions inherited from ipe::PdfPainter
static void drawColor (Stream &stream, Color color, const char *gray, const char *rgb)
- Protected Attributes inherited from ipe::PdfPainter
StreamiStream
std::list< StateiActiveState

Constructor & Destructor Documentation

PsPainter::PsPainter ( const Cascade style,
Stream stream 
)
PsPainter::~PsPainter ( )

Member Function Documentation

void PsPainter::doNewPath ( )
protectedvirtual

Perform new path operator.

Reimplemented from ipe::PdfPainter.

void PsPainter::doDrawPath ( TPathMode  mode)
protectedvirtual

Actually draw the path.

Reimplemented from ipe::PdfPainter.

void PsPainter::doDrawBitmap ( Bitmap  bitmap)
protectedvirtual

Draw a bitmap.

Reimplemented from ipe::PdfPainter.

void PsPainter::doAddClipPath ( )
protectedvirtual

Add a clip path.

Reimplemented from ipe::PdfPainter.


The documentation for this class was generated from the following files:
  • ipepswriter.h
  • ipepswriter.cpp

ipe-7.1.4/build/doc/classipe_1_1_pdf_painter-members.html0000644000175000017500000005732112120621776023166 0ustar otfriedotfried Ipelib: Member List
ipe::PdfPainter Member List

This is the complete list of members for ipe::PdfPainter, including all inherited members.

addClipPath()ipe::Painter
cascade() const ipe::Painterinline
closePath()ipe::Painter
curveTo(const Vector &v1, const Vector &v2, const Vector &v3)ipe::Painter
curveTo(const Bezier &bezier)ipe::Painterinline
dashStyle() const ipe::Painterinline
dashStyle(std::vector< double > &dashes, double &offset) const ipe::Painter
doAddClipPath()ipe::PdfPainterprotectedvirtual
doClosePath()ipe::PdfPainterprotectedvirtual
doCurveTo(const Vector &v1, const Vector &v2, const Vector &v3)ipe::PdfPainterprotectedvirtual
doDrawArc(const Arc &arc)ipe::Painterprotectedvirtual
doDrawBitmap(Bitmap bitmap)ipe::PdfPainterprotectedvirtual
doDrawPath(TPathMode mode)ipe::PdfPainterprotectedvirtual
doDrawSymbol(Attribute symbol)ipe::PdfPainterprotectedvirtual
doDrawText(const Text *text)ipe::PdfPainterprotectedvirtual
doLineTo(const Vector &v)ipe::PdfPainterprotectedvirtual
doMoveTo(const Vector &v)ipe::PdfPainterprotectedvirtual
doNewPath()ipe::PdfPainterprotectedvirtual
doPop()ipe::PdfPainterprotectedvirtual
doPush()ipe::PdfPainterprotectedvirtual
drawArc(const Arc &arc)ipe::Painter
drawArcAsBezier(double alpha)ipe::Painterprotected
drawAttributes()ipe::PdfPainterprotected
drawBitmap(Bitmap bitmap)ipe::Painter
drawColor(Stream &stream, Color color, const char *gray, const char *rgb)ipe::PdfPainterstatic
drawEllipse()ipe::Painter
drawOpacity()ipe::PdfPainterprotected
drawPath(TPathMode mode)ipe::Painter
drawSymbol(Attribute symbol)ipe::Painter
drawText(const Text *text)ipe::Painter
fill() const ipe::Painterinline
fillRule() const ipe::Painterinline
gradient() const ipe::Painterinline
iActiveStateipe::PdfPainterprotected
iCascadeipe::Painterprotected
iInPathipe::Painterprotected
iMatrixipe::Painterprotected
iStateipe::Painterprotected
iStreamipe::PdfPainterprotected
lineCap() const ipe::Painterinline
lineJoin() const ipe::Painterinline
lineTo(const Vector &v)ipe::Painter
matrix() const ipe::Painterinline
moveTo(const Vector &v)ipe::Painter
newPath()ipe::Painter
opacity() const ipe::Painterinline
Painter(const Cascade *style)ipe::Painter
PdfPainter(const Cascade *style, Stream &stream)ipe::PdfPainter
pen() const ipe::Painterinline
pop()ipe::Painter
popMatrix()ipe::Painter
push()ipe::Painter
pushMatrix()ipe::Painter
rect(const Rect &re)ipe::Painter
setDashStyle(Attribute dash)ipe::Painter
setFill(Attribute color)ipe::Painter
setFillRule(TFillRule rule)ipe::Painter
setGradient(Attribute grad)ipe::Painter
setLineCap(TLineCap cap)ipe::Painter
setLineJoin(TLineJoin join)ipe::Painter
setOpacity(Attribute opaq)ipe::Painter
setPen(Attribute pen)ipe::Painter
setStroke(Attribute color)ipe::Painter
setSymFill(Attribute color)ipe::Painter
setSymPen(Attribute wid)ipe::Painter
setSymStroke(Attribute color)ipe::Painter
setTiling(Attribute til)ipe::Painter
stroke() const ipe::Painterinline
symFill() const ipe::Painterinline
symPen() const ipe::Painterinline
symStroke() const ipe::Painterinline
tiling() const ipe::Painterinline
transform(const Matrix &m)ipe::Painter
translate(const Vector &v)ipe::Painter
untransform(TTransformations trans)ipe::Painter
~Painter()ipe::Paintervirtual
~PdfPainter()ipe::PdfPainterinlinevirtual

ipe-7.1.4/build/doc/functions_func_0x73.html0000644000175000017500000007013612120621776020523 0ustar otfriedotfried Ipelib: Class Members - Functions
 

- s -


ipe-7.1.4/build/doc/classipe_1_1_matrix-members.html0000644000175000017500000001743412120621776022200 0ustar otfriedotfried Ipelib: Member List
ipe::Matrix Member List

This is the complete list of members for ipe::Matrix, including all inherited members.

aipe::Matrix
inverse() const ipe::Matrix
isIdentity() const ipe::Matrixinline
linear() const ipe::Matrixinline
Matrix()ipe::Matrixinline
Matrix(const Linear &linear)ipe::Matrixinline
Matrix(const Linear &linear, const Vector &t)ipe::Matrixinlineexplicit
Matrix(double m11, double m21, double m12, double m22, double t1, double t2)ipe::Matrixinlineexplicit
Matrix(const Vector &v)ipe::Matrixinlineexplicit
Matrix(String str)ipe::Matrixexplicit
operator*(const Vector &rhs) const ipe::Matrixinline
operator*(const Bezier &rhs) const ipe::Matrixinline
operator*(const Bezier &rhs) constipe::Matrixrelated
operator*(const Vector &rhs) constipe::Matrixrelated
operator*(const Matrix &lhs, const Matrix &rhs)ipe::Matrixrelated
operator*(const Matrix &lhs, const Arc &rhs)ipe::Matrixrelated
operator<<(Stream &stream, const Matrix &rhs)ipe::Matrixrelated
operator==(const Matrix &rhs) const ipe::Matrixinline
translation() const ipe::Matrixinline

ipe-7.1.4/build/doc/structipe_1_1_painter_1_1_state.html0000644000175000017500000002642612120621776022766 0ustar otfriedotfried Ipelib: ipe::Painter::State Struct Reference
ipe::Painter::State Struct Reference

#include <ipepainter.h>

Public Attributes

Color iStroke
Color iFill
Fixed iPen
String iDashStyle
TLineCap iLineCap
TLineJoin iLineJoin
TFillRule iFillRule
Color iSymStroke
Color iSymFill
Fixed iSymPen
Fixed iOpacity
Attribute iTiling
Attribute iGradient

Member Data Documentation

Color ipe::Painter::State::iStroke
Color ipe::Painter::State::iFill
Fixed ipe::Painter::State::iPen
String ipe::Painter::State::iDashStyle
TLineCap ipe::Painter::State::iLineCap
TLineJoin ipe::Painter::State::iLineJoin
TFillRule ipe::Painter::State::iFillRule
Color ipe::Painter::State::iSymStroke
Color ipe::Painter::State::iSymFill
Fixed ipe::Painter::State::iSymPen
Fixed ipe::Painter::State::iOpacity
Attribute ipe::Painter::State::iTiling
Attribute ipe::Painter::State::iGradient

The documentation for this struct was generated from the following file:
  • ipepainter.h

ipe-7.1.4/build/doc/classipe_1_1_face.html0000644000175000017500000002126312120621776020135 0ustar otfriedotfried Ipelib: ipe::Face Class Reference

#include <ipefonts.h>

Public Member Functions

 Face (int id, const Font &font)
 ~Face ()
bool matches (int id) const
Font::TType type () const
int width (int ch) const
cairo_font_face_t * cairoFont ()
int getGlyph (int ch)

Detailed Description

A typeface (aka font), actually loaded (from a font file or PDF file).

Constructor & Destructor Documentation

Face::Face ( int  id,
const Font font 
)
Face::~Face ( )

Member Function Documentation

bool ipe::Face::matches ( int  id) const
inline
Font::TType ipe::Face::type ( ) const
inline
int ipe::Face::width ( int  ch) const
inline
cairo_font_face_t* ipe::Face::cairoFont ( )
inline
int Face::getGlyph ( int  ch)

The documentation for this class was generated from the following files:
  • ipefonts.h
  • ipefonts.cpp

ipe-7.1.4/build/doc/manual_31.html0000644000175000017500000000507012120621776016472 0ustar otfriedotfried Ipe Manual -- 7.3 Bookmarks
7.4 Gradient patterns7 Presentations7.2 Views7.3 Bookmarks

7.3 Bookmarks

You can set a section title and a subsection title for each page of an Ipe document. Theses titles will be shown in the bookmarks list (right-click on a toolbar to make it visible). Double-clicking a title brings you directly to its page, making navigation of long documents much easier. The titles are also exported to PDF, and are visible in the bookmarks view of PDF viewers.

ipe-7.1.4/build/doc/structipe_1_1_gradient_1_1_stop-members.html0000644000175000017500000000546212120621776024413 0ustar otfriedotfried Ipelib: Member List
ipe::Gradient::Stop Member List

This is the complete list of members for ipe::Gradient::Stop, including all inherited members.

coloripe::Gradient::Stop
offsetipe::Gradient::Stop

ipe-7.1.4/build/doc/manual_2.html0000644000175000017500000001143412120621776016411 0ustar otfriedotfried Ipe Manual -- 2 About Ipe files
3 General ConceptsTop1 Introduction2 About Ipe files

2 About Ipe files

Ipe 7 creates (Encapsulated) Postscript or PDF files. These files can be used in any way that PDF or Postscript files are used, such as viewed with Ghostview, with Acrobat Reader or Xpdf, edited with Acrobat, or included in Latex/Pdflatex documents. However, Ipe cannot read arbitrary Postscript or PDF files, only files it has created itself. This is because files created by Ipe contain a special hidden stream that describes the Ipe objects. (So if you edit your Ipe-generated PDF file in a different program such as Adobe Acrobat, Ipe will not be able to read the file again afterwards.)

You decide in what format to store a figure when saving it for the first time. Ipe gives you the option of saving with extensions "eps" (Encapsulated Postscript), "pdf" (PDF), and "ipe" (XML). Only documents consisting of a single page can be stored in Encapsulated Postscript format, as this format doesn't support multi-page documents. Files saved with extension "ipe" are XML files and contain no Postscript of PDF information. The precise XML format used by Ipe is documented later in this manual. XML files can be read by any XML-aware parser, and it is easy for other programs to generate XML output to be read by Ipe. You probably don't want to keep your figures in XML format, but it is excellent for communicating with other programs, and for converting figures between programs.

There are a few interesting uses for Ipe documents:

Figures for Latex documents.

Ipe was originally written to make it easy to make figures for Latex documents. If you are not familiar with including figures in Latex, you can find details here.

Presentations.

Ipe is not a presentation tool like Powerpoint or Keynote. An Ipe presentation is simply a PDF file that has been created by Ipe, and which you present during your talk using, say, Acrobat Reader on an LCD projector. The chapter on presentations explains Ipe features meant for making presentations.

SVG files.

Figures in SVG format can be used to include scalable figures in web pages. Ipe does not save in SVG format directly, but the tool "iperender" allows you to convert an Ipe document to SVG format. This conversion is one-way, although the auxiliary tool svgtoipe also allows you to convert SVG figures to Ipe format.

Bitmaps.

Sometimes Ipe can be useful for creating bitmap images. Again, the "iperender" tool can render an Ipe document as a bitmap in PNG format.

Explain Auto-exporting.

ipe-7.1.4/build/doc/luapage.html0000644000175000017500000002254212120621776016333 0ustar otfriedotfried Ipelib: Lua bindings for Document, Page, and StyleSheet
Lua bindings for Document, Page, and StyleSheet

Stylesheet

A stylesheet can be constructed by reading from a file (in XML format), or by creating an empty stylesheet:

sheet = ipe.Sheet("filename")
-- returns sheet or nil, error message
sheet = ipe.Sheet()    -- empty stylesheet

Stylesheets have the following methods:

sheet:clone()            -- returns a private copy of the stylesheet
sheet:xml(with_bitmaps)  -- return XML representation 
sheet:add(kind, symbolic, value)
sheet:set(kind, value)
sheet:isStandard()      -- is this the built-in stylesheet?
sheet:name()            -- name of the stylesheet
sheet:setName(name)

sheet:add adds a definition for symbolic name to the stylesheet. Permissible values for kind are:

 pen, symbolsize, arrowsize, color, dashstyle, textsize, textstretch, 
 textstyle, gridsize, anglesize, opacity, symbol, 

sheet:set sets a value. Permissible values for kind are:

 preamble, linecap, linejoin, fillrule

Stylesheet cascade

Documents own an entire stack of style sheets, the style sheet cascade. An empty style sheet cascade can be created like this:

sheets = ipe.Sheets()

or you can obtain one from an Ipe document.

Style sheet cascades have the following methods:

sheets1 = sheets:clone()              -- make a private copy
sheets:allNames(kind)
sheets:find(kind, symbolic)
sheets:has(kind, symbolic)
sheets:count()                        -- return number of sheets
sheets:sheet(index)                   -- return sheet at index
sheets:insert(index, style_sheet)     -- insert sheet at index
sheets:remove(index)                  -- delete a sheet
log = sheets:update(directory)        -- update style sheets from directory

sheets:allNames returns a table with all symbolic names defined in the entire stylesheet cascade. Permissible values for kind are:

 pen, symbolsize, arrowsize, color, dashstyle, textsize, textstretch, 
 textstyle, gridsize, anglesize, opacity, tiling, symbol, gradient, effect

sheet:has checks whether a symbolic name is defined in the cascade. Permissible values for kind are as for allNames.

sheet:find looks up a symbolic definition. Permissible values for kind are:

 pen, symbolsize, arrowsize, color, dashstyle, textsize, textstretch, 
 textstyle, gridsize, anglesize, opacity, symbol, 
 preamble, linecap, linejoin, fillrule, layout

Page

Page objects can be created like this:

p = ipe.Page()   -- create basic page with one layer and one view
p1 = p:clone()   -- returns a copy of the page

The following methods act on the views of a page. Note that views are indexed starting from 1, as usual in Lua.

p:countViews() 
p:effect(view)
p:setEffect(view, effect)
p:active(view)
p:setActive(view, layer)
p:insertView(view, layer)
p:removeView(view)
p:clearViews()
f = p:viewMarked(view) -- return true/false
p:setViewMarked(view, f)

The following methods act on the layers of a page. Note that layers are always accessed by name, not by index as in C++.

p:countLayers()
p:layers()        -- return table of layer names
p:isLocked(layer)
p:setLocked(layer)
p:hasSnapping(layer)
p:setSnapping(layer)
p:renameLayer(oldname, newname)
p:addLayer(name)     -- or create name if nil (name is returned)
p:removeLayer(layer)
p:moveLayer(layer, target_index)
p:visible(view, layer)   -- is layer visible in view?
p:setVisible(view, layer, boolean)

The objects of a page can be accessed by indexing, using an iterator, or with various methods. Note that object indices start with 1, as usual in Lua.

-- objects:

#p      -- return number of objects on page
p[i]    -- return object #i, where 1 <= i <= #p

-- iterate over objects of page:
for i, obj, sel, layer in p:objects() do
  print(i, obj, sel, layer)
end

p:select(objno)              -- returns nil, 1, or 2
p:setSelect(objno, status)   -- status is nil, 1, or 2
p:layerOf(objno)
p:setLayerOf(objno, layer)
p:visible(view, objno)       -- is object visible in view?
p:bbox(objno)                -- cached by page
p:invalidateBBox(objno)      -- invalidate cached bbox
p:insert(objno, object, select, layer)  -- objno == nil means append
p:remove(objno)
p:replace(objno, object)     -- automatically clones object
p:transform(objno, matrix)

-- returns true if attribute was actually changed
p:setAttribute(objno, property, value, stroke, fill) 

Finally, there are various methods to query and modify the currently selected objects, the page title and sections, etc.:

-- selection:
obj = p:primarySelection() -- nil if no primary selection
p:hasSelection()           -- true or false
p:deselectAll()
p:ensurePrimarySelection()

-- t is a table with fields "title", "section", "subsection"
-- if section or subsection is not a string, the title is used 
t = p:titles()  
p:setTitles(t)

-- n is a string
n = p:notes()
p:setNotes(n)

-- f is true/false
f = p:marked()
p:setMarked(f)

-- misc:
rect = p:textBox(sheets)   -- box for next text box

Document

Documents have the following methods:

doc = ipe.Document()         -- empty document
doc = ipe.Document(filename) -- load from file 
-- returns either document or nil, error message, error code

#doc    -- number of pages
doc[i]  -- return page #i, where 1 <= i <= #doc

-- format == nil: guess from filename
-- flags is either nil, or a table with keys
-- "export", "nozip", "lastview", "nocolor"
doc:save(filename, format, flags)  
doc:exportPages(filename, flags, fromPage, toPage)
doc:exportView(filename, format, flags, pageNo, viewNo)

-- iterating over pages of document:
for i, p in doc:pages() do
  print("Page number",  i, p)
end

doc:set(no, page)         -- replace with a clone of page, returns old page
doc:insert(no, page)
doc:append(page)
doc:remove(no)            -- returns page and removes from document
doc:countTotalViews()
doc:sheets()              -- returns style sheet cascade
old = doc:replaceSheets(sheets)  -- replace and return old cascade
doc:has(what)  -- where what in { "truetype", "gradients", "tilings", "transparency" }
doc:runLatex()
-- returns either true, nil, result code, logfile
--         or     false, error message, result code, logfile

doc:fontPool()    -- returns light userdata
doc:checkStyle()  -- returns list of undefined symbolic names
t = doc:properties()  -- returns table
doc:setProperties(t)  -- changes properties set in table

doc:properties() returns a table with the following fields (all fields exist even if their contents is an empty string):

title author subject keywords preamble created modified creator
fullscreen cropbox numberpages 

Other functions

ipe.fileFormat(filename)      -- returns one of "xml", "pdf", "eps", "ipe5", "unknown"
ipe.fileExists(filename)      -- returns true or false
beziers = ipe.splineToBeziers(spline, is_closed)
ipelet = ipe.Ipelet(dllname)  -- loads C++ ipelet from absolute path
-- returns ipelet or nil, error message

ipe-7.1.4/build/doc/classipe_1_1_ps_writer-members.html0000644000175000017500000000741012120621776022703 0ustar otfriedotfried Ipelib: Member List
ipe::PsWriter Member List

This is the complete list of members for ipe::PsWriter, including all inherited members.

createHeader(int pno=0, int vno=0)ipe::PsWriter
createPageView(int pno=0, int vno=0)ipe::PsWriter
createTrailer()ipe::PsWriter
createXml(int compressLevel)ipe::PsWriter
PsWriter(TellStream &stream, const Document *doc, bool noColor)ipe::PsWriter
~PsWriter()ipe::PsWriter

ipe-7.1.4/build/doc/classipe_1_1_buffer_source-members.html0000644000175000017500000000607112120621776023520 0ustar otfriedotfried Ipelib: Member List
ipe::BufferSource Member List

This is the complete list of members for ipe::BufferSource, including all inherited members.

BufferSource(const Buffer &buffer)ipe::BufferSource
getChar()ipe::BufferSourcevirtual
~DataSource()=0ipe::DataSourcepure virtual

ipe-7.1.4/build/doc/classipe_1_1_image.html0000644000175000017500000011061312120621776020317 0ustar otfriedotfried Ipelib: ipe::Image Class Reference

#include <ipeimage.h>

Inherits ipe::Object.

Public Member Functions

 Image (const Rect &rect, Bitmap bitmap)
 Image (const XmlAttributes &attr, String data)
 Image (const XmlAttributes &attr, Bitmap bitmap)
virtual Objectclone () const
virtual ImageasImage ()
virtual Type type () const
virtual void saveAsXml (Stream &stream, String layer) const
virtual void draw (Painter &painter) const
virtual void drawSimple (Painter &painter) const
virtual void accept (Visitor &visitor) const
virtual double distance (const Vector &v, const Matrix &m, double bound) const
virtual void addToBBox (Rect &box, const Matrix &m, bool) const
virtual void snapVtx (const Vector &mouse, const Matrix &m, Vector &pos, double &bound) const
Rect rect () const
Bitmap bitmap () const
- Public Member Functions inherited from ipe::Object
virtual ~Object ()=0
virtual GroupasGroup ()
virtual TextasText ()
virtual PathasPath ()
virtual ReferenceasReference ()
virtual TPinned pinned () const
void setPinned (TPinned pin)
TTransformations transformations () const
void setTransformations (TTransformations trans)
void setMatrix (const Matrix &matrix)
const Matrixmatrix () const
virtual bool setAttribute (Property prop, Attribute value, Attribute stroke, Attribute fill)
virtual Attribute getAttribute (Property prop)
virtual void checkStyle (const Cascade *sheet, AttributeSeq &seq) const
virtual void snapBnd (const Vector &mouse, const Matrix &m, Vector &pos, double &bound) const

Additional Inherited Members

- Public Types inherited from ipe::Object
enum  Type {
  EGroup, EPath, EText, EImage,
  EReference
}
- Protected Member Functions inherited from ipe::Object
 Object ()
 Object (const AllAttributes &attr)
 Object (const Object &rhs)
 Object (const XmlAttributes &attr)
void saveAttributesAsXml (Stream &stream, String layer) const
- Static Protected Member Functions inherited from ipe::Object
static void checkSymbol (Kind kind, Attribute attr, const Cascade *sheet, AttributeSeq &seq)
- Protected Attributes inherited from ipe::Object
Matrix iMatrix
TPinned iPinned: 8
TTransformations iTransformations: 8

Detailed Description

The image object.

Constructor & Destructor Documentation

Image::Image ( const Rect rect,
Bitmap  bitmap 
)
explicit

Create a new image.

Image::Image ( const XmlAttributes attr,
String  data 
)
explicit

Create from XML stream.

Image::Image ( const XmlAttributes attr,
Bitmap  bitmap 
)
explicit

Create from XML stream with given bitmap.

Member Function Documentation

Object * Image::clone ( ) const
virtual

Clone object.

Implements ipe::Object.

Image * Image::asImage ( )
virtual

Return pointer to this object.

Reimplemented from ipe::Object.

Object::Type Image::type ( ) const
virtual

Implements ipe::Object.

void Image::saveAsXml ( Stream stream,
String  layer 
) const
virtual

Save image in XML stream.

Implements ipe::Object.

void Image::draw ( Painter painter) const
virtual

Draw image.

Implements ipe::Object.

void Image::drawSimple ( Painter painter) const
virtual

Draw simple version for selecting and transforming.

Implements ipe::Object.

void Image::accept ( Visitor visitor) const
virtual

Call VisitImage of visitor.

Implements ipe::Object.

double Image::distance ( const Vector v,
const Matrix m,
double  bound 
) const
virtual

Return distance of transformed object to point v. If larger than bound, can just return bound.

Implements ipe::Object.

void Image::addToBBox ( Rect box,
const Matrix m,
bool  cp 
) const
virtual

Extend box to include the object transformed by m.

For objects in a page, don't call this directly. The Page caches the bounding box of each object, so it is far more efficient to call Page::bbox.

Control points that lie outside the visual object are included if cp is true.

If called with an empty box and cp == false, the result of this function is a tight bounding box for the object, with a little leeway in case the boundary is determined by a spline (it has to be approximated to perform this operation).

Implements ipe::Object.

void Image::snapVtx ( const Vector mouse,
const Matrix m,
Vector pos,
double &  bound 
) const
virtual

Compute possible vertex snapping position for transformed object.

Looks only for positions closer than bound. If successful, modify pos and bound.

Implements ipe::Object.

Rect ipe::Image::rect ( ) const
inline

Return the rectangle occupied by the image on the paper.

The transformation matrix is applied to this, of course.

Bitmap ipe::Image::bitmap ( ) const
inline

Return Bitmap of the image.


The documentation for this class was generated from the following files:
  • ipeimage.h
  • ipeimage.cpp

ipe-7.1.4/build/doc/functions_func_0x69.html0000644000175000017500000002336212120621776020527 0ustar otfriedotfried Ipelib: Class Members - Functions
 

- i -


ipe-7.1.4/build/doc/class_ipe_auto_ptr.html0000644000175000017500000002013312120621776020566 0ustar otfriedotfried Ipelib: IpeAutoPtr< T > Class Template Reference
IpeAutoPtr< T > Class Template Reference

#include <ipebase.h>

Public Member Functions

 IpeAutoPtr (T *ptr)
 ~IpeAutoPtr ()
T * operator-> ()
T & operator* ()
T * ptr ()
T * take ()

Constructor & Destructor Documentation

template<class T >
IpeAutoPtr< T >::IpeAutoPtr ( T *  ptr)
inline
template<class T >
IpeAutoPtr< T >::~IpeAutoPtr ( )
inline

Member Function Documentation

template<class T >
T* IpeAutoPtr< T >::operator-> ( )
inline
template<class T >
T& IpeAutoPtr< T >::operator* ( )
inline
template<class T >
T* IpeAutoPtr< T >::ptr ( )
inline
template<class T >
T* IpeAutoPtr< T >::take ( )
inline

The documentation for this class was generated from the following file:
  • ipebase.h

ipe-7.1.4/build/doc/structipe_1_1_pdf_token.html0000644000175000017500000002070112120621776021423 0ustar otfriedotfried Ipelib: ipe::PdfToken Struct Reference
ipe::PdfToken Struct Reference

#include <ipepdfparser.h>

Public Types

enum  TToken {
  EErr, EOp, EName, ENumber,
  EString, ETrue, EFalse, ENull,
  EArrayBg, EArrayEnd, EDictBg, EDictEnd
}

Public Attributes

TToken iType
String iString

Detailed Description

A PDF lexical token.

Member Enumeration Documentation

The various types of tokens.

Enumerator:
EErr 
EOp 
EName 
ENumber 
EString 
ETrue 
EFalse 
ENull 
EArrayBg 
EArrayEnd 
EDictBg 
EDictEnd 

Member Data Documentation

TToken ipe::PdfToken::iType

The type of this token.

String ipe::PdfToken::iString

The string representing this token.


The documentation for this struct was generated from the following file:
  • ipepdfparser.h

ipe-7.1.4/build/doc/example4.svg0000644000175000017500000001235512120621776016270 0ustar otfriedotfried ipe-7.1.4/build/doc/doxygen.png0000644000175000017500000000730312120621776016210 0ustar otfriedotfried‰PNG  IHDRh ;ˆØŠIDATxí]y\•Õº~45%TL Q”PE"q–Û11±]8a„w*©¨(*â" ˆzÀè`8 ¨‰¢mÅ,’òà„p$%”œBó(8k†Ü÷ýÜû6lòö»§k÷Ç÷[ÏÞß·Ö;?k½ëßÕÕÕPxÑêÏ't´ÏùÈ€zÀÇÅ3_€Q4€g@œmÿ ¾ò‰âci‰ôçÿ{ ðÇð¬ù~½Á€4:õHcÂü ðŸÁ³„ª'ÕPÆæ P7^h،♠zb„cóP¨„ 3‚† Ò}çÿO²qÁºNkÝTÛ(É?d Ç~z<’«4Óǡ؞Þv­zµÙ¦õ¬ZâdÛ,Ë6Ók±]Fz< ¾ZçƒsÕ?ìƒsUø2SÉåwê1”c`[ì—}%ѽ.Ô¼6‚BLZ˜û!F8[ ¹…×TéÛ— »Þ#gó]å:vžu?‡vèbÙR˜?wùŽŸ¾ÊÐgbÑÉÌÕ$kF~Ê;عÆ•¢ïX®?ÉèlÆÙôõà»Nʪ¼­,ìHC§gAz•ÆlÓº­gÑú ]œjÎñåM…3ÓÚæoÒ³'=‘$Ò÷f}G•ŸS_‡öèco.Êȹ :ó£ Ãds®Ù:1=¼{ƒå9?÷ý…zqÛvîÓi‰D’p¿Ë šmÙíoÛâýaÖüEqÒµwÌ}¿~{òj€ç{ôºŸFNëí[ëOq·ÇOSúXO]°>‚‚muæÄ¾e¤“5Ë{¨JÕ¯£(›´«bÂçû’ÍlÓÅ}žïú`éUÞy„ac§Á†ÔCºŠóAkl‘±y¥†ô¢ùôs÷Aø¬7ÄõôoJ±äÄ ù.¥Be. Z¬Ð×ÇÈöå¹­ù'Ù-PëìŠyF.ž‚žÝÚ€lp&.êˆð•jò7’re’z19»ã§HGíø%œüq°ïüz׈c¬_k_")ŸHJnÐÑ~ˆÐÖ˜á´äÕ5 µÁq€ÿ5#¸·îà¶+9T‘‚ ðŽ÷Rܸrz“Ï´Ì =Ï…{ðáO£Èf ¡Íwg|Ž’Ü/¢Þ$÷¯¢ëðúÀ;¿à¨Ö™âÒÆ­]¯ÜW"Þ/< ‡÷DÏà°½üB}çyIEc^—ƒ=[V“Ýh²ëMä$l];Kû®¸ýr¦È*Åò ÿtÒõ$]•MŸ÷´;×I€1èó!‚œõ¸M õ¨(fÌæ<ÁÎÎò5~z¿ù¶ž mÌêÕ >–âÚ©âëˆIÎÞçz;ãu[i·eç^ÆÜÙÓ³NÞëF6B\}7†»+üŽÓ,Ã'a ½˜-yHY¿,‘^—ñfú~ß?Hcø¸…¸ñó{Z+4\såƒû·¯Ù·nߣð«íFÆ¡sغëû§D¾?ò<–Ævkx0ÅM±ælذÁIÓxÿd”žÜÉ÷EE»AªM«g*È£YEí7Û™^[uíý®v[wGå†=Ed¼n×¶ÆæÖÅl¡'¨pGÚk+‹æ¢À¬¨C8ªâš2 dz3H£ß ¡¨BÒûSÃÅù[wŘ ~xpçútÁæmö¤Å£¥iQæ­‰AB1ÉfÙ‰›4u¹ïìIÒ]Ë6äò%ÿ†† 1t.’NJph¬zÌ ÎR1Ž"3-"¸‡‹&ìó°1âüžìó[:‡ï„¼‘……N m–“W0®_èÜœ ×õ6ùò&»)Æìꦬýæ}¬ñ~»{múù]z½£M•ºP~^Îá:eQTÙ_*7ÕÄ9É8—·Ëï 3°¶47E•î¿u÷“SÉ»U¯ _ NíºôW¬e¸ÄNÓ|»;™¿;ŒæÅd"ȉôøòÞµõï¾®½"èÄ´ÖMM+bYµ‘_ÉæEÝüÎ]P»¹XKÐI½Þ¥oE<_¹(„EP±Œ|mÇÁ¡‘Ý,ŠÓ©ººZ±Îߺ§×kÝ,kÍMš`Äø…jzeU»æ ™Át3ÓÀ½˜6—ÒöùË·r¨¹Ñ}““wö:Χùë¼ ¿|‚TܵÉQˆKßç_ÁâÀ™œ”pÑÐóໃ¼Ydâ0!®àa –øöçW$ÃÁ‘Á$/\¬$ð 2ÞímÞLH‹Ÿ èd£HVÜ,:ò½»RÍZšJ­a„z*>‹_…NT(ù‚^SVF­U¹8ñEþôñ܈óùnd;«®8™\C]ø=Èêm¬Æ:‚´ÆbãDd=Áãßžˆ‹UU5O‹|]þð®Pèêv‰á\]2ßìÿ"yÈ[ïyʧz£g{Y«{„Ùø5©ÿ;w{N3é­nâĨw§Á¢ÍK¢Ý­ûÏ29Id¿’ì y)ìPÞò8ŒÅ©¯‰±@mPÔñwjl,6 áhWÕ˜d öà uõmÁp®.™á£Ç…twöR x­BδYcŒxg*vo  yò‘•“[¬?ÜVœ˜0ÒN¡O난~Žó’¯·h#´Hkýœ±8kÓß^Àq@]àÓ“ø,56´¯÷Í-κU»n…[>]@nîøÏœp›[œ6# €4tën¯:ŽÒþ}…—8äT9_žY$/´G’K™©ù†•(óÑ’Mø©`ŸÉdѺ;ùO‹B Ó&P{qöhJÉ+Úé–§¦l2«MïöÝ_1ÑÓ«’t¸½±l€ëØya ¦ô©«®½ÆL^¬žêñš¸ùy.¾Û½Š[ u/]½‹iS}øN>²e1™q‡jfÚ&¢©iT\=kÏ›ÀXô-.84V5ðu!TE˜ þ.ŒOH´¶4—zwTr.ï‰¦Ë xõµ·œÖ„HÆù£žÈHùg Ñhñ’T$ßyq¸zþ¨p¿´ë< q•ró÷š‰wÿÍÑð–I]´–æI²é²˜sÂ"×:Õ–bÕ¦“ÈÙL6¢9VÊÓWž§<æ;”3?ý©Mê3AV#µ±ËÞ¯‘ž K£UrÝ9!›qát¦H£Ù+6ÇV…/TS^pÃùqgLP'Ú5E ‚–ÀÞºîÄ Ën"2|Ÿ;®W»Îý"Ö¬TwÖâµtúŽO'› á+W Ã+¦âZÌ–<ÕÆ&nOÝ,IŠ£06.ÁZ.Çñúøh*INÚ’Oe½ÉgBXÐÔZóäøä9èü“hÒíDSš¥¡Ê µA¯/Ôc¸ö“`A§¯"zå|‘ €ÅŸ¨ú;HÍ#‚Î|%ÄOˆƒ«OàÌÉÐÜD ž mÜðâc–ƤÉÂqm¶uË&~÷núÒË £ÇÏ€ZÕj =«_n[‡‡÷nN§ÏÝ$_¾bE˜‚€Õ)ù8¾?6‘lú“ÍÙæÖ}#bW( œ³d-®•p&¡ý’œÖa”"9öõņÐ$’Ú›AÜ!ä;ÐÑõè{~á¹8‘ÛÞ£1ÛÓÉ0ž`²#´kÒuäNÅÖ Q¹bhæ ”8ûÓMáŽa›•¿”w±h²¢®qŠæ°(bK ‚’Z¾Ò%ÐÆémáãÖË(Éý‚ÛJ)@> þ›7% ï{y Á“¾ÆÒîohfòô>{pÿ.­_Î%±ÉèägëlZØ\B2B #™¸ÚüÒºp‚hÝšü®[¥Ü<‹#SpñÌA7’ãØHƒt4:Ÿ|g¨tÓL¶*($Æ©»ì…®ù’ó÷$;b›ÔÙ`=¶£¦M„MÌÄ5ò«·Ç¾“H·ÌH.¼žHeAîº5}r­dõ¨±)ÀT};€Q5iÖ2…O0ü…0óñÃ;óæ,Š´²µ냔}g‘£]‹7å9ˆà©_{üèîêžC>úhê{Ž .ÈìðIIð€?[Kswz6Òuíý¬;µ€ç§OåâJÉa˶zv°éd† ¤µâ‚l´é舊«Åüy¾c÷ÁèÖÍ'ràúÅ™TWÕôÓ°¡L €|ʽŒ¼ì­høBã ÝTëî'ò]Kø£ìâÏ(=¹Kx €¿ LÌ,Pý¤Êµu‡¹…׈ §Å¾÷à1Ý«Äý;¿pGDäxZYÛ kfæ6¸ùóæ7®œ®þ6·ÕoÚ¾ÔH~ò®Þ¸â 8Uø“p<ºw3¡a£ÏÑ’‘3èÏ"€bˆ-ÎܺÏ_ªÅ]+ËM©zü°s“f-êçhÇãÑýÊãôÿ5}ZQNb{Ó?å%ÿ\SUõعIÓæ}~}p[œoÔÄ„êÐMMZáNÅå@>Œ„²á6(?¡Åé âK½+ü?À%ÝÝ·/Ç1‚9áUø?B)”ÕèâÞlÈÒêÏ @=àùÄÞžk­®ÅIEND®B`‚ipe-7.1.4/build/doc/manual_28.html0000644000175000017500000000517312120621776016504 0ustar otfriedotfried Ipe Manual -- 7 Presentations
8 Advanced topicsTop6 Stylesheets7 Presentations

7 Presentations

An Ipe presentation is an Ipe PDF document that is presented using, for instance, Acrobat Reader and a video projector. Ipe has a number of features that make it easier to make such presentations.

ipe-7.1.4/build/doc/classipe_1_1_canvas-members.html0000644000175000017500000007326012120621776022146 0ustar otfriedotfried Ipelib: Member List
ipe::Canvas Member List

This is the complete list of members for ipe::Canvas, including all inherited members.

additionalModifiers() const ipe::CanvasBaseinline
Canvas(GtkWidget *parent)ipe::Canvas
Canvas(QWidget *parent, Qt::WFlags f=0)ipe::Canvas
Canvas(HWND parent)ipe::Canvas
CanvasBase()ipe::CanvasBaseprotected
canvasHeight() const ipe::CanvasBaseinline
canvasStyle() const ipe::CanvasBaseinline
canvasTfm() const ipe::CanvasBase
canvasWidth() const ipe::CanvasBaseinline
cascade() const ipe::CanvasBaseinline
center() const ipe::CanvasBaseinline
computeFifi(double x, double y)ipe::CanvasBaseprotected
devToUser(const Vector &arg) const ipe::CanvasBase
drawAxes(cairo_t *cc)ipe::CanvasBaseprotected
drawFrame(cairo_t *cc)ipe::CanvasBaseprotected
drawGrid(cairo_t *cc)ipe::CanvasBaseprotected
drawObjects(cairo_t *cc)ipe::CanvasBaseprotected
drawPaper(cairo_t *cc)ipe::CanvasBaseprotected
drawTool(Painter &painter)ipe::CanvasBaseprotected
EAlt enum valueipe::CanvasBase
EControl enum valueipe::CanvasBase
ECrossCursor enum valueipe::CanvasBase
EDotCursor enum valueipe::CanvasBase
EHandCursor enum valueipe::CanvasBase
EMeta enum valueipe::CanvasBase
EShift enum valueipe::CanvasBase
EStandardCursor enum valueipe::CanvasBase
finishTool()ipe::CanvasBase
globalPos() const ipe::CanvasBaseinline
iAdditionalModifiersipe::CanvasBaseprotected
iAutoOriginipe::CanvasBaseprotected
iAutoSnapipe::CanvasBaseprotected
iCascadeipe::CanvasBaseprotected
iDimmedipe::CanvasBaseprotected
iFifiVisibleipe::CanvasBaseprotected
iFontsipe::CanvasBaseprotected
iGlobalPosipe::CanvasBaseprotected
iHeightipe::CanvasBaseprotected
iMousePosipe::CanvasBaseprotected
init(HINSTANCE hInstance)ipe::Canvasstatic
invalidate()ipe::Canvasprotectedvirtual
invalidate(int x, int y, int w, int h)ipe::Canvasprotectedvirtual
iObserveripe::CanvasBaseprotected
iOldFifiipe::CanvasBaseprotected
iPageipe::CanvasBaseprotected
iPageNumberipe::CanvasBaseprotected
iPanipe::CanvasBaseprotected
iRepaintObjectsipe::CanvasBaseprotected
iSelectionVisibleipe::CanvasBaseprotected
iSnapipe::CanvasBaseprotected
iStyleipe::CanvasBaseprotected
iSurfaceipe::CanvasBaseprotected
iToolipe::CanvasBaseprotected
iUnsnappedMousePosipe::CanvasBaseprotected
iViewipe::CanvasBaseprotected
iWidthipe::CanvasBaseprotected
iZoomipe::CanvasBaseprotected
keyPressEvent(QKeyEvent *ev)ipe::Canvasprotectedvirtual
mouseMoveEvent(QMouseEvent *ev)ipe::Canvasprotectedvirtual
mousePressEvent(QMouseEvent *ev)ipe::Canvasprotectedvirtual
mouseReleaseEvent(QMouseEvent *ev)ipe::Canvasprotectedvirtual
paintEvent(QPaintEvent *ev)ipe::Canvasprotectedvirtual
pan() const ipe::CanvasBaseinline
pos() const ipe::CanvasBaseinline
refreshSurface()ipe::CanvasBaseprotected
setAdditionalModifiers(int mod)ipe::CanvasBase
setAutoOrigin(const Vector &v)ipe::CanvasBase
setCanvasStyle(const Style &style)ipe::CanvasBase
setCursor(TCursor cursor, double w=1.0, Color *color=0)ipe::Canvasvirtual
setDimmed(bool dimmed)ipe::CanvasBase
setFifiVisible(bool visible)ipe::CanvasBase
setFontPool(const FontPool *fontPool)ipe::CanvasBase
setObserver(CanvasObserver *observer)ipe::CanvasBase
setPage(const Page *page, int pno, int view, const Cascade *sheet)ipe::CanvasBase
setPan(const Vector &v)ipe::CanvasBase
setSelectionVisible(bool visible)ipe::CanvasBase
setSnap(const Snap &s)ipe::CanvasBase
setTool(Tool *tool)ipe::CanvasBase
setZoom(double zoom)ipe::CanvasBase
simpleSnapPos() const ipe::CanvasBase
sizeHint() const ipe::Canvasprotectedvirtual
snap() const ipe::CanvasBaseinline
snapToPaperAndFrame()ipe::CanvasBaseprotected
tabletEvent(QTabletEvent *ev)ipe::Canvasprotectedvirtual
TCursor enum nameipe::CanvasBase
TModifiers enum nameipe::CanvasBase
unsnappedPos() const ipe::CanvasBaseinline
update()ipe::CanvasBase
updateTool()ipe::CanvasBase
userToDev(const Vector &arg) const ipe::CanvasBase
wheelEvent(QWheelEvent *ev)ipe::Canvasprotectedvirtual
window() const ipe::Canvasinline
windowId() const ipe::Canvasinline
zoom() const ipe::CanvasBaseinline
~Canvas()ipe::Canvas
~CanvasBase()ipe::CanvasBasevirtual

ipe-7.1.4/build/doc/classipe_1_1_ipelet-members.html0000644000175000017500000000606012120621776022147 0ustar otfriedotfried Ipelib: Member List
ipe::Ipelet Member List

This is the complete list of members for ipe::Ipelet, including all inherited members.

ipelibVersion() const =0ipe::Ipeletpure virtual
run(int function, IpeletData *data, IpeletHelper *helper)=0ipe::Ipeletpure virtual
~Ipelet()=0ipe::Ipeletpure virtual

ipe-7.1.4/build/doc/functions_0x62.html0000644000175000017500000001730312120621776017503 0ustar otfriedotfried Ipelib: Class Members
Here is a list of all class members with links to the classes they belong to:

- b -


ipe-7.1.4/build/doc/structipe_1_1_tiling-members.html0000644000175000017500000000556312120621776022401 0ustar otfriedotfried Ipelib: Member List
ipe::Tiling Member List

This is the complete list of members for ipe::Tiling, including all inherited members.

iAngleipe::Tiling
iStepipe::Tiling
iWidthipe::Tiling

ipe-7.1.4/build/doc/pages.html0000644000175000017500000000317612120621776016016 0ustar otfriedotfried Ipelib: Related Pages
Related Pages
Here is a list of all related documentation pages:

ipe-7.1.4/build/doc/classipe_1_1_object_factory.html0000644000175000017500000001513412120621776022234 0ustar otfriedotfried Ipelib: ipe::ObjectFactory Class Reference

#include <ipefactory.h>

Static Public Member Functions

static ObjectcreateObject (String name, const XmlAttributes &attr, String data)
static ObjectcreateImage (String name, const XmlAttributes &attr, Bitmap bitmap)

Detailed Description

Factory for Ipe leaf objects.

Member Function Documentation

Object * ObjectFactory::createObject ( String  name,
const XmlAttributes attr,
String  data 
)
static

Create an Ipe object by calling the right constructor.

Object * ObjectFactory::createImage ( String  name,
const XmlAttributes attr,
Bitmap  bitmap 
)
static

Create an Image with a given bitmap.


The documentation for this class was generated from the following files:
  • ipefactory.h
  • ipefactory.cpp

ipe-7.1.4/build/doc/ftv2node.png0000644000175000017500000000012612120621776016256 0ustar otfriedotfried‰PNG  IHDRɪ|IDATxíݱðøScOx@ –¨y}IEND®B`‚ipe-7.1.4/build/doc/functions_vars.html0000644000175000017500000006770112120621776017766 0ustar otfriedotfried Ipelib: Class Members - Variables
 

- a -

- c -

- d -

- i -

- n -

- o -

- p -

- t -

- x -

- y -

- z -


ipe-7.1.4/build/doc/classipe_1_1_color.html0000644000175000017500000003437112120621776020361 0ustar otfriedotfried Ipelib: ipe::Color Class Reference

#include <ipeattributes.h>

Public Member Functions

 Color ()
 Color (String str)
 Color (int r, int g, int b)
void save (Stream &stream) const
void saveRGB (Stream &stream) const
bool isGray () const
bool operator== (const Color &rhs) const
bool operator!= (const Color &rhs) const

Public Attributes

Fixed iRed
Fixed iGreen
Fixed iBlue

Related Functions

(Note that these are not member functions.)

Streamoperator<< (Stream &stream, const Color &attr)

Detailed Description

An absolute RGB color.

Constructor & Destructor Documentation

ipe::Color::Color ( )
inline

Default constructor.

Color::Color ( String  str)
explicit

Construct a color from a string.

If only a single number is given, this is a gray value, otherwise red, green, and blue components must be given.

Color::Color ( int  red,
int  green,
int  blue 
)
explicit

Construct a color.

Arguments red, green, blue range from 0 to 1000.

Member Function Documentation

void Color::save ( Stream stream) const

Save to stream.

void Color::saveRGB ( Stream stream) const

Save to stream in long format.

The RGB components are saved separately even for gray colors.

bool Color::isGray ( ) const

is it an absolute gray value?

bool Color::operator== ( const Color rhs) const
bool ipe::Color::operator!= ( const Color rhs) const
inline

Friends And Related Function Documentation

Stream & operator<< ( Stream stream,
const Color attr 
)
related

Member Data Documentation

Fixed ipe::Color::iRed
Fixed ipe::Color::iGreen
Fixed ipe::Color::iBlue

The documentation for this class was generated from the following files:
  • ipeattributes.h
  • ipeattributes.cpp

ipe-7.1.4/build/doc/functions_func_0x67.html0000644000175000017500000001773112120621776020530 0ustar otfriedotfried Ipelib: Class Members - Functions
 

- g -


ipe-7.1.4/build/doc/classipe_1_1_xml_parser-members.html0000644000175000017500000001454012120621776023043 0ustar otfriedotfried Ipelib: Member List
ipe::XmlParser Member List

This is the complete list of members for ipe::XmlParser, including all inherited members.

eos()ipe::XmlParserinline
getChar()ipe::XmlParserinline
iChipe::XmlParserprotected
iPosipe::XmlParserprotected
iSourceipe::XmlParserprotected
isTagChar(int ch)ipe::XmlParserinline
iTopElementipe::XmlParserprotected
parseAttributes(XmlAttributes &attr, bool qm=false)ipe::XmlParser
parsePCDATA(String tag, String &pcdata)ipe::XmlParser
parsePosition() const ipe::XmlParserinline
parseToTag()ipe::XmlParser
parseToTagX()ipe::XmlParserprotected
skipWhitespace()ipe::XmlParser
XmlParser(DataSource &source)ipe::XmlParser
~XmlParser()ipe::XmlParservirtual

ipe-7.1.4/build/doc/classipe_1_1_linear.html0000644000175000017500000004260012120621776020507 0ustar otfriedotfried Ipelib: ipe::Linear Class Reference

#include <ipegeo.h>

Public Member Functions

 Linear ()
 Linear (Angle angle)
 Linear (double m11, double m21, double m12, double m22)
 Linear (String str)
Linear inverse () const
bool isIdentity () const
Vector operator* (const Vector &rhs) const
bool operator== (const Linear &rhs) const
double determinant () const

Public Attributes

double a [4]

Related Functions

(Note that these are not member functions.)

Streamoperator<< (Stream &stream, const Linear &rhs)
Vector operator* (const Vector &rhs) const
Linear operator* (const Linear &lhs, const Linear &rhs)

Detailed Description

Linear transformation in the plane (2x2 matrix).

Constructor & Destructor Documentation

ipe::Linear::Linear ( )
inline

Create identity matrix.

Linear::Linear ( Angle  angle)
explicit

Create matrix representing a rotation by angle.

ipe::Linear::Linear ( double  m11,
double  m21,
double  m12,
double  m22 
)
inlineexplicit

Create linear matrix with given coefficients.

Linear::Linear ( String  str)
explicit

Parse string.

Member Function Documentation

Linear Linear::inverse ( ) const

Return inverse.

bool ipe::Linear::isIdentity ( ) const
inline

Is this the identity matrix?

Vector ipe::Linear::operator* ( const Vector rhs) const
inline
bool ipe::Linear::operator== ( const Linear rhs) const
inline

Check for equality of two linear matrices.

double ipe::Linear::determinant ( ) const
inline

Return determinant of a linear matrix.

Friends And Related Function Documentation

Stream & operator<< ( Stream stream,
const Linear rhs 
)
related
Vector operator* ( const Vector rhs) const
related

Linear matrix times vector.

Linear operator* ( const Linear lhs,
const Linear rhs 
)
related

Linear matrix multiplication.

Member Data Documentation

double ipe::Linear::a[4]

The documentation for this class was generated from the following files:
  • ipegeo.h
  • ipegeo.cpp

ipe-7.1.4/build/doc/manual_44.html0000644000175000017500000003426012120621776016501 0ustar otfriedotfried Ipe Manual -- 9.3 Ipe object elements
9.4 The <ipestyle> element9 The Ipe file format9.2 The <page> element9.3 Ipe object elements

9.3 Ipe object elements

Common attributes

layer
(optional) Only allowed on "top-level" objects, that is, objects directly inside a <page> element. The value indicates into which layer the object goes. If the attribute is missing, the object goes into the same layer as the preceding object. If the first object has no layer attribute, it goes into the layer defined first in the page, or the default "alpha" layer.
matrix
(optional) A sequence of six real numbers, separated by white space, indicating a transformation matrix for all coordinates inside the element (including embedded elements if this is a <group> element). A missing matrix attribute is interpreted as the identity matrix.
pin
(optional) Possible values are yes (object is fixed on the page), h (object is pinned horizontally, but can move in the vertical direction), and v (the opposite). The default is no pinning.
transformations
(optional) This attribute determines how objects can be deformed by transformations. Possible values are affine (the default), rigid, and translations.

Color attribute values

A color attribute value is either a symbolic name defined in one of the style sheets of the document, one of the predefined names "black" or "white", a single real number between 0 (black) and 1 (white) indicating a gray level, or three real numbers in the range [0,1] indicating the red, green, and blue component (in this order), separated by white space.

Path construction operators

Graphical shapes in Ipe are described using a series of "path construction operators" with arguments. This generalizes the PDF path construction syntax.

Each operator follows its arguments. The operators are

  • m (moveto) (1 point argument): begin new subpath,
  • l (lineto) (1 point argument): add straight segment to subpath,
  • c (curveto) (3 point arguments): add a cubic Bézier spline,
  • q (quadratic curveto) (2 point arguments): add a quadratic Bézier spline,
  • e (ellipse) (1 matrix argument): add a closed subpath consisting of an ellipse, the ellipse is the image of the unit circle under the transformation described by the matrix,
  • a (arcto) (1 matrix argument, 1 point argument): add an elliptic arc, on the ellipse describe by the matrix, from current position to given point,
  • s (spline) (n point arguments): add a uniform cubic B-spline with n + 5 control points (current position and nth point have multiplicity 3),
  • u (closed spline) (n point arguments): add a closed subpath consisting of a closed uniform B-spline with n control points.
  • h (closepath) (no arguments): close the current subpath. No more segments can be added to this subpath, so the next operator (if there is one) must start a new subpath.
Paths consisting of more than one closed loop are allowed. A subpath can consist of any mix of straight segments, quadratic and cubic Bézier splines, elliptic arcs, and B-splines.

9.3.1 The <group> element

The <group> element allows to group objects together, so that they appear as one in the user interface.

Attributes

clip
(optional) The value is a sequence of path construction operators, forming a clipping path for the objects inside the group.

The contents of the <group> element is a series of Ipe object elements.

9.3.2 The <image> element

Attributes

bitmap
(required) Value is an integer referring to a bitmap defined in a <bitmap> element in the document,
rect
(required) Four real coordinates separated by white space, in the order x1, y1, x2, y2, indicating two opposite corners of the image in Ipe coordinates).

The image element is normally empty. However, it is allowed to omit the bitmap attribute. In this case, the <image> must carry all the attributes of the <bitmap> element, with the exception of id. The element contents is then the bitmap data, as described for <bitmap>.

9.3.3 The <use> element

The <use> element refers to a symbol (an Ipe object) defined in the style sheet. The attributes stroke, fill, pen, and size make sense only when the symbol accepts these parameters.

Attributes

name
(required) The name of a symbol defined in a style sheet of the document.
pos
(optional) Position of the symbol on the page (two real numbers, separated by white space). This is the location of the origin of the symbol coordinate system. The default is the origin.
stroke
(optional) A stroke color (used whereever the symbol uses the symbolic color "sym-stroke"). The default is black.
fill
(optional) A fill color (used whereever the symbol uses the symbolic color "sym-fill"). The default is white.
pen
(optional) A line width (used whereever the symbol uses the symbolic value "sym-pen"). The default is "normal".
size
(optional) The size of the symbol, either a symbolic size (of type "symbol size"), or an absolute scaling factor. The default is 1.0.

The <use> element must be empty.

9.3.4 The <text> element

Attributes

stroke
(optional) The stroke color. If the attribute is missing, black will be used.
type
(required) Possible values are label and minipage.
size
(optional) The font size—either a symbolic name defined in a style sheet, or a real number. The default is "normal".
pos
(required) Two real numbers separated by white space, defining the position of the text on the paper.
width
(required for minipage objects, optional for label objects) The width of the object in points.
height
(optional) The total height of the object in points.
depth
(optional) The depth of the object in points.
valign
(optional) Possible values are top (default for a minipage object), bottom (default for a label object), center, and baseline.
halign
(optional, label only) Possible values are left, right, and center. left is the default. This determines the position of the reference point with respect to the text box.
style
(optional, minipage only) Selects a LaTeX "style" to be used for formatting the text, and must be a symbolic name defined in a style sheet. The standard style sheet defines the styles "normal", "center", "itemize", and "item". If the attribute is not present, the "normal" style is applied.
opacity
(optional) Opacity of the element. This must be a symbolic name. The default is 1.0, meaning fully opaque.

The dimensions are recomputed by Ipe when running LaTeX, with the exception of width for minipage objects whose width is fixed.

The contents of the <text> element must be a legal LaTeX fragment that can be interpreted by LaTeX inside \hbox, possibly using the macros or packages defined in the preamble.

9.3.5 The <path> element

Attributes

stroke
(optional) The stroke color. If the attribute is missing, the shape will not be stroked.
fill
(optional) The fill color. If the attribute is missing, the shape will not be filled.
dash
(optional) Either a symbolic name defined in a style sheet, or a dash pattern in PDF format, such as "[3 1] 0" for "three pixels on, one off, starting with the first pixel". If the attribute is missing, a solid line is drawn.
pen
(optional) The line width, either symbolic (defined in a style sheet), or as a single real number. The default value is "normal".
cap
(optional) The line cap setting of PDF as an integer. If the argument is missing, the setting from the style sheet is used.
join
(optional) The line join setting of PDF as an integer. If the argument is missing, the setting from the style sheet is used.
fillrule
(optional) Possible values are wind and eofill, selecting one of two algorithms for determining whether a point lies inside a filled object. If the argument is missing, the setting from the style sheet is used.
arrow
(optional) The value consists of a symbolic name, say "triangle" for an arrow type (a symbol with name "arrow/triangle(spx)"), followed by a slash and the size of the arrow. The size is either a symbolic name (of type "arrowsize") defined in a style sheet, or a real number. If the attribute is missing, no arrow is drawn.
rarrow
(optional) Same for an arrow in the reverse direction (at the beginning of the first subpath).
opacity
(optional) Opacity of the element. This must be a symbolic name. The default is 1.0, meaning fully opaque.
tiling
(optional) A tiling pattern to be used to fill the element. The default is not to tile the element. If the element is not filled, then the tiling pattern is ignored.
gradient
(optional) A gradient pattern to be used to fill the element. If the element is not filled, then the gradient pattern is ignored. (The fill color is only used for rendering where gradients are not available, for instance currently in Postscript.) If gradient is set, then tiling is ignored.

The contents of the <path> element is a sequence of path construction operators. The entire shape will be stroked and/or filled with a single stroke and fill operation.

ipe-7.1.4/build/doc/classipe_1_1_ipelet_helper.html0000644000175000017500000002423612120621776022063 0ustar otfriedotfried Ipelib: ipe::IpeletHelper Class Reference

#include <ipelet.h>

Public Types

enum  {
  EOkButton, EOkCancelButtons, EYesNoCancelButtons, EDiscardCancelButtons,
  ESaveDiscardCancelButtons
}

Public Member Functions

virtual ~IpeletHelper ()=0
virtual void message (const char *msg)=0
virtual int messageBox (const char *text, const char *details, int buttons)=0
virtual bool getString (const char *prompt, String &str)=0

Detailed Description

Service provider for Ipelets.

C++ Ipelets can ask Ipe to perform various services and request information using this class.

Member Enumeration Documentation

anonymous enum
Enumerator:
EOkButton 
EOkCancelButtons 
EYesNoCancelButtons 
EDiscardCancelButtons 
ESaveDiscardCancelButtons 

Constructor & Destructor Documentation

IpeletHelper::~IpeletHelper ( )
pure virtual

Pure virtual destructor.

Member Function Documentation

virtual void ipe::IpeletHelper::message ( const char *  msg)
pure virtual

Show a message in the status bar.

virtual int ipe::IpeletHelper::messageBox ( const char *  text,
const char *  details,
int  buttons 
)
pure virtual

Pop up a modal message box.

The details can be null.

 Choose one of EOkButton, EOkCancelButtons, EYesNoCancelButtons,
 EDiscardCancelButtons, ESaveDiscardCancelButtons
 for \a buttons. 

 Returns 1 for Ok or Yes, 0 for No, -1 for Cancel.  
virtual bool ipe::IpeletHelper::getString ( const char *  prompt,
String str 
)
pure virtual

Pop up a modal dialog asking the user to enter a string. Returns true if the user didn't cancel the dialog.


The documentation for this class was generated from the following files:
  • ipelet.h
  • ipeutils.cpp

ipe-7.1.4/build/doc/classipe_1_1_painter.html0000644000175000017500000023406212120621776020704 0ustar otfriedotfried Ipelib: ipe::Painter Class Reference

#include <ipepainter.h>

Inherited by ipe::BBoxPainter, ipe::CairoPainter, ipe::PdfPainter, and IpeQtPainter.

Classes

struct  State

Public Member Functions

 Painter (const Cascade *style)
virtual ~Painter ()
void transform (const Matrix &m)
void untransform (TTransformations trans)
void translate (const Vector &v)
void push ()
void pop ()
void pushMatrix ()
void popMatrix ()
void newPath ()
void moveTo (const Vector &v)
void lineTo (const Vector &v)
void curveTo (const Vector &v1, const Vector &v2, const Vector &v3)
void curveTo (const Bezier &bezier)
void rect (const Rect &re)
void drawEllipse ()
void drawArc (const Arc &arc)
void closePath ()
void drawPath (TPathMode mode)
void drawBitmap (Bitmap bitmap)
void drawText (const Text *text)
void drawSymbol (Attribute symbol)
void addClipPath ()
void setStroke (Attribute color)
void setFill (Attribute color)
void setPen (Attribute pen)
void setDashStyle (Attribute dash)
void setLineCap (TLineCap cap)
void setLineJoin (TLineJoin join)
void setFillRule (TFillRule rule)
void setSymStroke (Attribute color)
void setSymFill (Attribute color)
void setSymPen (Attribute wid)
void setOpacity (Attribute opaq)
void setTiling (Attribute til)
void setGradient (Attribute grad)
const Cascadecascade () const
Color stroke () const
Color fill () const
const Matrixmatrix () const
Fixed pen () const
String dashStyle () const
void dashStyle (std::vector< double > &dashes, double &offset) const
TLineCap lineCap () const
TLineJoin lineJoin () const
TFillRule fillRule () const
Color symStroke () const
Color symFill () const
Fixed symPen () const
Fixed opacity () const
Attribute tiling () const
Attribute gradient () const

Protected Member Functions

virtual void doPush ()
virtual void doPop ()
virtual void doNewPath ()
virtual void doMoveTo (const Vector &v)
virtual void doLineTo (const Vector &v)
virtual void doCurveTo (const Vector &v1, const Vector &v2, const Vector &v3)
virtual void doDrawArc (const Arc &arc)
virtual void doClosePath ()
virtual void doDrawPath (TPathMode mode)
virtual void doDrawBitmap (Bitmap bitmap)
virtual void doDrawText (const Text *text)
virtual void doDrawSymbol (Attribute symbol)
virtual void doAddClipPath ()
void drawArcAsBezier (double alpha)

Protected Attributes

std::list< StateiState
std::list< MatrixiMatrix
const CascadeiCascade
int iInPath

Detailed Description

Interface for drawing.

Painter-derived classes are used for drawing to the screen and for generating PDF and Postscript output.

The Painter maintains a stack of graphics states, which includes stroke and fill color, line width, dash style, miter limit, line cap and line join. It also maintains a separate stack of transformation matrices. The Painter class takes care of maintaining the stacks, and setting of the attributes in the current graphics state.

Setting an attribute with a symbolic value is resolved immediately using the stylesheet Cascade attached to the Painter, so calling the stroke() or fill() methods of Painter will return the current absolute color.

It's okay to set symbolic attributes that the stylesheet does not define - they are set to a default absolute value (black, solid, etc.).

The painter is either in "general" or in "path construction" mode. The newPath() member starts path construction mode. In this mode, only the path construction operators (moveTo, lineTo, curveTo, rect, drawArc, closePath), the transformation operators (transform, untransform, translate), and the matrix stack operators (pushMatrix, popMatrix) are admissible. The path is drawn using drawPath, this ends path construction mode. Path construction operators cannot be used in general mode.

The graphics state for a path must be set before starting path construction mode, that is, before calling newPath().

Derived classes need to implement the doXXX functions for drawing paths, images, and texts. The transformation matrix has already been applied to the coordinates passed to the doXXX functions.

Constructor & Destructor Documentation

Painter::Painter ( const Cascade style)

Constructor takes a (cascaded) style sheet, which is not owned.

The initial graphics state contains all default attributes.

Painter::~Painter ( )
virtual

Virtual destructor.

Member Function Documentation

void Painter::transform ( const Matrix m)

Concatenate a matrix to current transformation matrix.

void Painter::untransform ( TTransformations  trans)

Reset transformation to original one, but with different origin/direction.

This changes the current transformation matrix to the one set before the first push operation, but maintaining the current origin. Only the operations allowed in allowed are applied.

void Painter::translate ( const Vector v)

Concatenate a translation to current transformation matrix.

void Painter::push ( )

Save current graphics state.

Cannot be called in path construction mode.

void Painter::pop ( )

Restore previous graphics state.

Cannot be called in path construction mode.

void Painter::pushMatrix ( )

Save current transformation matrix.

void Painter::popMatrix ( )

Restore previous transformation matrix.

void Painter::newPath ( )

Enter path construction mode.

void Painter::moveTo ( const Vector v)

Start a new subpath.

void Painter::lineTo ( const Vector v)

Add line segment to current subpath.

void Painter::curveTo ( const Vector v1,
const Vector v2,
const Vector v3 
)

Add a Bezier segment to current subpath.

void ipe::Painter::curveTo ( const Bezier bezier)
inline

Overloaded function.

Assumes current position is bezier.iV[0]

void Painter::rect ( const Rect re)

Add a rectangle subpath to the path.

This is implemented in terms of moveTo() and lineTo().

void ipe::Painter::drawEllipse ( )
void Painter::drawArc ( const Arc arc)

Add an elliptic arc to current path.

Assumes the current point is arc.beginp().

void Painter::closePath ( )

Close the current subpath.

void Painter::drawPath ( TPathMode  mode)

Fill and/or stroke a path.

As in PDF, a "path" can consist of several subpaths. Whether it is filled or stroked depends on mode.

void Painter::drawBitmap ( Bitmap  bitmap)

Render a bitmap.

Assumes the transformation matrix has been set up to map the unit square to the image area on the paper.

void Painter::drawText ( const Text text)

Render a text object.

Stroke color is already set, and the origin is the lower-left corner of the text box (not the reference point!).

void Painter::drawSymbol ( Attribute  symbol)

Render a symbol.

The current coordinate system is already the symbol coordinate system. If the symbol is parameterized, then sym-stroke, sym-fill, and sym-pen are already set.

void Painter::addClipPath ( )

Add current path as clip path.

void Painter::setStroke ( Attribute  color)

Set stroke color, resolving symbolic color and "sym-x" colors.

void Painter::setFill ( Attribute  color)

Set fill color, resolving symbolic color.

void Painter::setPen ( Attribute  pen)

Set pen, resolving symbolic value.

void Painter::setDashStyle ( Attribute  dash)

Set dash style, resolving symbolic value.

void Painter::setLineCap ( TLineCap  cap)

Set line cap.

If cap is EDefaultCap, the current setting remains unchanged.

void Painter::setLineJoin ( TLineJoin  join)

Set line join.

If join is EDefaultJoin, the current setting remains unchanged.

void Painter::setFillRule ( TFillRule  rule)

Set fill rule (wind or even-odd).

If the rule is EDefaultRule, the current setting remains unchanged.

void Painter::setSymStroke ( Attribute  color)

Set symbol stroke color, resolving symbolic color.

void Painter::setSymFill ( Attribute  color)

Set symbol fill color, resolving symbolic color.

void Painter::setSymPen ( Attribute  wid)

Set symbol pen, resolving symbolic pen.

void Painter::setOpacity ( Attribute  opaq)

Set opacity.

void Painter::setTiling ( Attribute  tiling)

Set tiling pattern.

If tiling is not normal, resets the gradient pattern.

void Painter::setGradient ( Attribute  grad)

Set gradient fill.

If grad is not normal, resets the tiling pattern.

const Cascade* ipe::Painter::cascade ( ) const
inline

Return style sheet cascade.

Color ipe::Painter::stroke ( ) const
inline

Return current stroke color.

Color ipe::Painter::fill ( ) const
inline

Return current fill color.

const Matrix& ipe::Painter::matrix ( ) const
inline

Return current transformation matrix.

Fixed ipe::Painter::pen ( ) const
inline

Return current pen.

String ipe::Painter::dashStyle ( ) const
inline

Return current dash style (always absolute attribute).

void Painter::dashStyle ( std::vector< double > &  dashes,
double &  offset 
) const

Return dashstyle as a double sequence.

TLineCap ipe::Painter::lineCap ( ) const
inline

Return current line cap.

TLineJoin ipe::Painter::lineJoin ( ) const
inline

Return current line join.

TFillRule ipe::Painter::fillRule ( ) const
inline

Return current fill rule.

Color ipe::Painter::symStroke ( ) const
inline

Return current symbol stroke color.

Color ipe::Painter::symFill ( ) const
inline

Return current symbol fill color.

Fixed ipe::Painter::symPen ( ) const
inline

Return current symbol pen.

Fixed ipe::Painter::opacity ( ) const
inline

Return current opacity.

Attribute ipe::Painter::tiling ( ) const
inline

Return current tiling.

Attribute ipe::Painter::gradient ( ) const
inline

Return current gradient fill.

void Painter::doPush ( )
protectedvirtual

Perform graphics state push on output medium.

Reimplemented in ipe::BBoxPainter, ipe::CairoPainter, and ipe::PdfPainter.

void Painter::doPop ( )
protectedvirtual

Perform graphics state pop on output medium.

Reimplemented in ipe::BBoxPainter, ipe::CairoPainter, and ipe::PdfPainter.

void Painter::doNewPath ( )
protectedvirtual

Perform new path operator.

Reimplemented in ipe::BBoxPainter, ipe::PdfPainter, and ipe::PsPainter.

void Painter::doMoveTo ( const Vector v)
protectedvirtual

Perform moveto operator.

The transformation matrix has already been applied.

Reimplemented in ipe::BBoxPainter, ipe::CairoPainter, and ipe::PdfPainter.

void Painter::doLineTo ( const Vector v)
protectedvirtual

Perform lineto operator.

The transformation matrix has already been applied.

Reimplemented in ipe::BBoxPainter, ipe::CairoPainter, and ipe::PdfPainter.

void Painter::doCurveTo ( const Vector v1,
const Vector v2,
const Vector v3 
)
protectedvirtual

Perform curveto operator.

The transformation matrix has already been applied.

Reimplemented in ipe::BBoxPainter, ipe::CairoPainter, and ipe::PdfPainter.

void Painter::doDrawArc ( const Arc arc)
protectedvirtual

Draw an elliptic arc.

The default implementations calls drawArcAsBezier(). The transformation matrix has not yet been applied to arc.

Reimplemented in ipe::CairoPainter.

void Painter::doClosePath ( )
protectedvirtual

Perform closepath operator.

Reimplemented in ipe::CairoPainter, and ipe::PdfPainter.

void Painter::doDrawPath ( TPathMode  mode)
protectedvirtual

Actually draw the path.

Reimplemented in ipe::BBoxPainter, ipe::CairoPainter, ipe::PdfPainter, and ipe::PsPainter.

void Painter::doDrawBitmap ( Bitmap  bitmap)
protectedvirtual

Draw a bitmap.

Reimplemented in ipe::BBoxPainter, ipe::CairoPainter, ipe::PdfPainter, and ipe::PsPainter.

void Painter::doDrawText ( const Text text)
protectedvirtual

Draw a text object.

Reimplemented in ipe::BBoxPainter, ipe::CairoPainter, and ipe::PdfPainter.

void Painter::doDrawSymbol ( Attribute  symbol)
protectedvirtual

Draw a symbol.

The default implementation calls the draw method of the object. Only PDF drawing overrides this to reuse a PDF XForm.

Reimplemented in ipe::PdfPainter.

void Painter::doAddClipPath ( )
protectedvirtual

Add a clip path.

Reimplemented in ipe::BBoxPainter, ipe::CairoPainter, ipe::PdfPainter, and ipe::PsPainter.

void Painter::drawArcAsBezier ( double  alpha)
protected

Draw an arc of the unit circle of length alpha.

PDF does not have an "arc" or "circle" primitive, so to draw an arc, circle, or ellipse, Ipe has to translate it into a sequence of Bezier curves.

The approximation is based on the following: The unit circle arc from (1,0) to (cos a, sin a) be approximated by a Bezier spline with control points (1, 0), (1, beta) and their mirror images along the line with slope a/2, where beta = 4.0 * (1.0 - cos(a/2)) / (3 * sin(a/2))

Ipe draws circles by drawing four Bezier curves for the quadrants, and arcs by patching together quarter circle approximations with a piece computed from the formula above.

alpha is normalized to [0, 2 pi], and applied starting from the point (1,0).

The function generates a sequence of Bezier splines as calls to curveTo. It is assumed that the caller has already executed a moveTo to the beginning of the arc at (1,0).

This function may modify the transformation matrix.

Member Data Documentation

std::list<State> ipe::Painter::iState
protected
std::list<Matrix> ipe::Painter::iMatrix
protected
const Cascade* ipe::Painter::iCascade
protected
int ipe::Painter::iInPath
protected

The documentation for this class was generated from the following files:
  • ipepainter.h
  • ipepainter.cpp

ipe-7.1.4/build/doc/ftv2mlastnode.png0000644000175000017500000000036612120621776017325 0ustar otfriedotfried‰PNG  IHDRɪ|½IDATxíÝ!NAÅñ¤‡à\ ÷à Um@`Ô5iÒ`ëh ‚ÅW7] b§ÝˆŠ&oföÍd¾YÔ4 üšcø ‡€´‹Åòù3v=¼]†§µ\B… I¿‹=B·™B¡®;¸k´µ W°ÍN@vyÍÑÖ4ãß÷]ÈâYìã§|M}]ÔÚx6a }ôdׇØYüú¨>¤||5?Ó>|žB"¡î'¡IEND®B`‚ipe-7.1.4/build/doc/classipe_1_1_text-members.html0000644000175000017500000005765412120621776021670 0ustar otfriedotfried Ipelib: Member List
ipe::Text Member List

This is the complete list of members for ipe::Text, including all inherited members.

accept(Visitor &visitor) const ipe::Textvirtual
addToBBox(Rect &box, const Matrix &m, bool) const ipe::Textvirtual
align() const ipe::Text
asGroup()ipe::Objectvirtual
asImage()ipe::Objectvirtual
asPath()ipe::Objectvirtual
asReference()ipe::Objectvirtual
asText()ipe::Textvirtual
checkStyle(const Cascade *sheet, AttributeSeq &seq) const ipe::Textvirtual
checkSymbol(Kind kind, Attribute attr, const Cascade *sheet, AttributeSeq &seq)ipe::Objectprotectedstatic
clone() const ipe::Textvirtual
depth() const ipe::Textinline
distance(const Vector &v, const Matrix &m, double bound) const ipe::Textvirtual
draw(Painter &painter) const ipe::Textvirtual
drawSimple(Painter &painter) const ipe::Textvirtual
EGroup enum valueipe::Object
EImage enum valueipe::Object
ELabel enum valueipe::Text
EMinipage enum valueipe::Text
EPath enum valueipe::Object
EReference enum valueipe::Object
EText enum valueipe::Object
getAttribute(Property prop)ipe::Textvirtual
getXForm() const ipe::Textinline
height() const ipe::Textinline
horizontalAlignment() const ipe::Textinline
iMatrixipe::Objectprotected
iPinnedipe::Objectprotected
isInternal() const ipe::Textinline
isMinipage() const ipe::Textinline
iTransformationsipe::Objectprotected
makeHAlign(String str, THorizontalAlignment def)ipe::Textstatic
makeVAlign(String str, TVerticalAlignment def)ipe::Textstatic
matrix() const ipe::Objectinline
Object()ipe::Objectexplicitprotected
Object(const AllAttributes &attr)ipe::Objectexplicitprotected
Object(const Object &rhs)ipe::Objectprotected
Object(const XmlAttributes &attr)ipe::Objectexplicitprotected
opacity() const ipe::Textinline
pinned() const ipe::Objectvirtual
position() const ipe::Textinline
saveAlignment(Stream &stream, THorizontalAlignment h, TVerticalAlignment v)ipe::Textstatic
saveAsXml(Stream &stream, String layer) const ipe::Textvirtual
saveAttributesAsXml(Stream &stream, String layer) const ipe::Objectprotected
setAttribute(Property prop, Attribute value, Attribute stroke, Attribute fill)ipe::Textvirtual
setHorizontalAlignment(THorizontalAlignment align)ipe::Text
setMatrix(const Matrix &matrix)ipe::Object
setOpacity(Attribute opaq)ipe::Text
setPinned(TPinned pin)ipe::Object
setSize(Attribute size)ipe::Text
setStroke(Attribute stroke)ipe::Text
setStyle(Attribute style)ipe::Text
setText(String text)ipe::Text
setTextType(TextType type)ipe::Text
setTransformations(TTransformations trans)ipe::Object
setVerticalAlignment(TVerticalAlignment align)ipe::Text
setWidth(double width)ipe::Text
setXForm(XForm *xform) const ipe::Text
size() const ipe::Textinline
snapBnd(const Vector &mouse, const Matrix &m, Vector &pos, double &bound) const ipe::Objectvirtual
snapVtx(const Vector &mouse, const Matrix &m, Vector &pos, double &bound) const ipe::Textvirtual
stroke() const ipe::Textinline
style() const ipe::Textinline
Text()ipe::Textexplicit
Text(const AllAttributes &attr, String data, const Vector &pos, TextType type, double width=10.0)ipe::Textexplicit
Text(const Text &rhs)ipe::Text
Text(const XmlAttributes &attr, String data)ipe::Textexplicit
text() const ipe::Textinline
textType() const ipe::Text
TextType enum nameipe::Text
totalHeight() const ipe::Textinline
transformations() const ipe::Objectinline
type() const ipe::Textvirtual
Type enum nameipe::Object
verticalAlignment() const ipe::Textinline
width() const ipe::Textinline
~Object()=0ipe::Objectpure virtual
~Text()ipe::Text

ipe-7.1.4/build/doc/example1.svg0000644000175000017500000002226112120621776016262 0ustar otfriedotfried ipe-7.1.4/build/doc/tab_a.png0000644000175000017500000000021612120621776015575 0ustar otfriedotfried‰PNG  IHDR$ÇÇ[UIDATxíK €0C'o¤(Šˆ[Žà%Üxÿ#Ù©­ç ùÁöó¦W¦e# 3t I 3+¼øEã~\D½9¯Ûàè’wM·¿öÿ}Yõ_êA4Yžã}IEND®B`‚ipe-7.1.4/build/doc/functions_enum.html0000644000175000017500000001033112120621776017742 0ustar otfriedotfried Ipelib: Class Members - Enumerations
 

ipe-7.1.4/build/doc/dir_7b54d492694b293bf8b54c70d2fe7f56.html0000644000175000017500000000575112120621776022103 0ustar otfriedotfried Ipelib: /home/otfried/Devel/ipe/src/ipecairo/ Directory Reference
ipecairo Directory Reference

Files

file  ipecairopainter.cpp
file  ipecairopainter.h
file  ipefonts.cpp
file  ipefonts.h
file  ipestdfonts.cpp
file  ipethumbs.cpp
file  ipethumbs.h

ipe-7.1.4/build/doc/classipe_1_1_arc.html0000644000175000017500000005554212120621776020013 0ustar otfriedotfried Ipelib: ipe::Arc Class Reference

#include <ipegeo.h>

Public Member Functions

 Arc ()
 Arc (const Matrix &m, Angle alpha, Angle beta)
 Arc (const Matrix &m)
 Arc (const Matrix &m0, const Vector &begp, const Vector &endp)
bool isEllipse () const
double distance (const Vector &v, double bound) const
double distance (const Vector &v, double bound, Vector &pos, Angle &angle) const
Rect bbox () const
Vector beginp () const
Vector endp () const
void intersect (const Line &l, std::vector< Vector > &result) const
void intersect (const Segment &s, std::vector< Vector > &result) const
void intersect (const Arc &a, std::vector< Vector > &result) const
void intersect (const Bezier &b, std::vector< Vector > &result) const

Public Attributes

Matrix iM
Angle iAlpha
Angle iBeta

Detailed Description

An arc of an ellipse.

The ellipse is represented using the matrix that transforms the unit circle x^2 + y^2 = 1 to the desired ellipse. The arc coordinate system is the coordinate system of this unit circle.

A full ellipse is described by iAlpha = 0, iBeta = IpeTwoPi.

An elliptic arc is the image of the circular arc from iAlpha to iBeta (in increasing angle in arc coordinate system).

Constructor & Destructor Documentation

ipe::Arc::Arc ( )
inline

Construct unit circle.

ipe::Arc::Arc ( const Matrix m,
Angle  alpha,
Angle  beta 
)
inline

Construct with given parameters.

ipe::Arc::Arc ( const Matrix m)
inline

Construct an ellipse.

Arc::Arc ( const Matrix m,
const Vector begp,
const Vector endp 
)

Construct arc for ellipse defined by m, from begp to endp.

This assumes that m has been correctly computed such that begb and endp already lie on the ellipse.

Member Function Documentation

bool ipe::Arc::isEllipse ( ) const
inline

Is this an entire ellipse?

double Arc::distance ( const Vector v,
double  bound 
) const

This doesn't really compute the distance, but a reasonable approximation.

double Arc::distance ( const Vector v,
double  bound,
Vector pos,
Angle angle 
) const

Like distance(), but sets pos to point on arc and angle to its angle in arc coordinates. angle and pos are not modified if result is larger than bound.

Rect Arc::bbox ( ) const

Return a tight bounding box.

Vector ipe::Arc::beginp ( ) const
inline

Return begin point of arc.

Vector ipe::Arc::endp ( ) const
inline

Return end point of arc.

void Arc::intersect ( const Line l,
std::vector< Vector > &  result 
) const

Compute intersection points of Arc with Line.

void Arc::intersect ( const Segment s,
std::vector< Vector > &  result 
) const

Compute intersection points of Arc with Segment.

void Arc::intersect ( const Arc a,
std::vector< Vector > &  result 
) const

Compute intersection points of Arc with Arc.

void Arc::intersect ( const Bezier b,
std::vector< Vector > &  result 
) const

Compute intersection points of Arc with Bezier.

Member Data Documentation

Matrix ipe::Arc::iM
Angle ipe::Arc::iAlpha
Angle ipe::Arc::iBeta

The documentation for this class was generated from the following files:
  • ipegeo.h
  • ipegeo.cpp

ipe-7.1.4/build/doc/classipe_1_1_shape-members.html0000644000175000017500000001653712120621776021777 0ustar otfriedotfried Ipelib: Member List
ipe::Shape Member List

This is the complete list of members for ipe::Shape, including all inherited members.

addToBBox(Rect &box, const Matrix &m, bool cp) const ipe::Shape
appendSubPath(SubPath *sp)ipe::Shape
countSubPaths() const ipe::Shapeinline
distance(const Vector &v, const Matrix &m, double bound) const ipe::Shape
draw(Painter &painter) const ipe::Shape
isSegment() const ipe::Shape
load(String data)ipe::Shape
operator=(const Shape &rhs)ipe::Shape
save(Stream &stream) const ipe::Shape
Shape()ipe::Shape
Shape(const Rect &rect)ipe::Shapeexplicit
Shape(const Segment &seg)ipe::Shapeexplicit
Shape(const Vector &center, double radius)ipe::Shapeexplicit
Shape(const Vector &center, double radius, double alpha0, double alpha1)ipe::Shapeexplicit
Shape(const Shape &rhs)ipe::Shape
snapBnd(const Vector &mouse, const Matrix &m, Vector &pos, double &bound) const ipe::Shape
snapVtx(const Vector &mouse, const Matrix &m, Vector &pos, double &bound) const ipe::Shape
subPath(int i) const ipe::Shapeinline
~Shape()ipe::Shape

ipe-7.1.4/build/doc/classipe_1_1_attribute-members.html0000644000175000017500000004532212120621776022674 0ustar otfriedotfried Ipelib: Member List
ipe::Attribute Member List

This is the complete list of members for ipe::Attribute, including all inherited members.

ARROW_ARC()ipe::Attributeinlinestatic
ARROW_FARC()ipe::Attributeinlinestatic
ARROW_NORMAL()ipe::Attributeinlinestatic
Attribute()ipe::Attributeinlineexplicit
Attribute(bool symbolic, String name)ipe::Attributeexplicit
Attribute(Fixed value)ipe::Attributeexplicit
Attribute(Color color)ipe::Attributeexplicit
Attribute(THorizontalAlignment align)ipe::Attributeinlineexplicit
Attribute(TVerticalAlignment align)ipe::Attributeinlineexplicit
Attribute(TLineJoin join)ipe::Attributeinlineexplicit
Attribute(TLineCap cap)ipe::Attributeinlineexplicit
Attribute(TFillRule rule)ipe::Attributeinlineexplicit
Attribute(TPinned pin)ipe::Attributeinlineexplicit
Attribute(TTransformations trans)ipe::Attributeinlineexplicit
Attribute(TPathMode pm)ipe::Attributeinlineexplicit
BACKGROUND()ipe::Attributeinlinestatic
BLACK()ipe::Attributeinlinestatic
Boolean(bool flag)ipe::Attributeinlinestatic
boolean() const ipe::Attributeinline
color() const ipe::Attribute
fillRule() const ipe::Attributeinline
horizontalAlignment() const ipe::Attributeinline
index() const ipe::Attributeinline
internal() const ipe::Attributeinline
isBoolean() const ipe::Attributeinline
isColor() const ipe::Attributeinline
isEnum() const ipe::Attributeinline
isNormal() const ipe::Attributeinline
isNumber() const ipe::Attributeinline
isString() const ipe::Attributeinline
isSymbolic() const ipe::Attributeinline
lineCap() const ipe::Attributeinline
lineJoin() const ipe::Attributeinline
makeColor(String str, Attribute deflt)ipe::Attributestatic
makeDashStyle(String str)ipe::Attributestatic
makeScalar(String str, Attribute deflt)ipe::Attributestatic
makeTextSize(String str)ipe::Attributestatic
normal(Kind kind)ipe::Attributestatic
NORMAL()ipe::Attributeinlinestatic
number() const ipe::Attribute
ONE()ipe::Attributeinlinestatic
OPAQUE()ipe::Attributeinlinestatic
operator!=(const Attribute &rhs) const ipe::Attributeinline
operator==(const Attribute &rhs) const ipe::Attributeinline
pathMode() const ipe::Attributeinline
pinned() const ipe::Attributeinline
string() const ipe::Attribute
StyleSheet classipe::Attributefriend
SYM_FILL()ipe::Attributeinlinestatic
SYM_PEN()ipe::Attributeinlinestatic
SYM_STROKE()ipe::Attributeinlinestatic
transformations() const ipe::Attributeinline
UNDEFINED()ipe::Attributeinlinestatic
verticalAlignment() const ipe::Attributeinline
WHITE()ipe::Attributeinlinestatic

ipe-7.1.4/build/doc/dir_d44c64559bbebec7f509842c48db8b23.html0000644000175000017500000001435012120621776022224 0ustar otfriedotfried Ipelib: /home/otfried/Devel/ipe/src/include/ Directory Reference
include Directory Reference

Files

file  ipeattributes.h
file  ipebase.h
file  ipebitmap.h
file  ipedoc.h
file  ipefactory.h
file  ipefontpool.h
file  ipegeo.h
file  ipegroup.h
file  ipeimage.h
file  ipeiml.h
file  ipelatex.h
file  ipelet.h
file  ipelib.h
file  ipeobject.h
file  ipepage.h
file  ipepainter.h
file  ipepath.h
file  ipepdfparser.h
file  ipepdfwriter.h
file  ipepswriter.h
file  ipereference.h
file  ipeshape.h
file  ipesnap.h
file  ipestyle.h
file  ipetext.h
file  ipeutils.h
file  ipexml.h

ipe-7.1.4/build/doc/up.png0000644000175000017500000000225012120621776015153 0ustar otfriedotfried‰PNG  IHDR D¤ŠÆsRGB®ÎégAMA± üa cHRMz&€„ú€èu0ê`:˜pœºQ<PLTEÿÿÿ™ÌÿÂõ†¹ì|¯âs¦ÙiœÏ_’ÅV‰¼L²Cv©:m 0c–&YŒPƒFy =p3f sx pHYsÄÄ•+IDAT8O}“Y„ D\@Íý/;dÍÇLyv’&tý#\sÒÝó.„OÀD7…ñ¢ˆ˜%O×X‰ð’f¢6ŠÀžóDG‘¨€ 5O´g¢Cjc1"Ú>Ƭ„^ó+ÿœÚ‹¢€Ó#?ñ_쵚ú¥€$Ò'‹ÈôìR€¥4ûÆ@òQ:š@!U ìMd€l6mn©mš'v=çÍÄ=àlféÕÖ!Ÿ5—%6¬Í¾d£ôPnÃÔwÁbÐð¡P‡¨ö0ªÑï 3eŒC…C4S£±*œ\¢}Weaä¹ó[X¶å} Ù–æÙ1 =Lk ݈Çë¾?„xxS ˆIEND®B`‚ipe-7.1.4/build/doc/functions_0x6f.html0000644000175000017500000002754112120621776017574 0ustar otfriedotfried Ipelib: Class Members
Here is a list of all class members with links to the classes they belong to:

- o -


ipe-7.1.4/build/doc/classipe_1_1_color-members.html0000644000175000017500000001244012120621776022002 0ustar otfriedotfried Ipelib: Member List
ipe::Color Member List

This is the complete list of members for ipe::Color, including all inherited members.

Color()ipe::Colorinline
Color(String str)ipe::Colorexplicit
Color(int r, int g, int b)ipe::Colorexplicit
iBlueipe::Color
iGreenipe::Color
iRedipe::Color
isGray() const ipe::Color
operator!=(const Color &rhs) const ipe::Colorinline
operator<<(Stream &stream, const Color &attr)ipe::Colorrelated
operator==(const Color &rhs) const ipe::Color
save(Stream &stream) const ipe::Color
saveRGB(Stream &stream) const ipe::Color

ipe-7.1.4/build/doc/manual_16.html0000644000175000017500000002653212120621776016503 0ustar otfriedotfried Ipe Manual -- 4.1 Path objects
4.2 Text objects4 Object types4.1 Path objects

4.1 Path objects

Path objects are defined by a set of subpaths, that is, curves in the plane. Each subpath is either open or closed, and consists of straight line segments, circular or elliptic arc segments, parabola segments (or, equivalently, quadratic Bézier splines), cubic Bézier splines, and cubic B-spline segments. The curves are drawn with the stroke color, dash style, and line width; the interior of the object specified is filled using the fill color.

The distinction between open and closed subpaths is meaningful for stroking only, for filling any open subpath is implicitely closed. Stroking a set of subpaths is identical to stroking them individually. This is not true for filling: using several subpaths, one can construct objects with holes, and more complicated pattern. The filling algorithm is normally the even-odd rule of Postscript/PDF: To determine whether a point lies inside the filled shape, draw a ray from that point in any direction, and count the number of path segments that cross the ray. If this number is odd, the point is inside; if even, the point is outside.

Ipe can draw arrows on the first and last segment of a path object, but only if that segment is part of an open subpath.

There are several Ipe modes that create path objects in different ways. All modes create an object consisting of a single subpath only. To make more complicated path objects, such as objects with holes, you create each boundary component separately, then select them all and use the Compose paths function in the Edit menu. The reverse operation is Decompose path, you find it in the context menu of a path object that has several subpaths.

You can also create complicated paths by joining curves sequentially. For this to work, the endpoint of one path must be (nearly) identical to the begin point of the next—easy to achieve using snapping. You select the path objects you wish to join, and call Join paths in the Edit menu. You can also join several open path objects into a single closed path this way.

Circles can be entered in three different ways. To create an ellipse, create a circle and stretch and rotate it. Circular arcs can be entered by clicking three points on the arc or by clicking the center of the supporting circle as well as the begin and end vertex of the arc. They can be filled in Postscript fashion, and can have arrows. You can stretch a circular arc to create an elliptic arc.

A common application for arcs is to mark angles in drawings. The snap keys are useful to create such arcs: set arc creation to center & 2 pts, select snap to vertex and snap to boundary, click first on the center point of the angle (which is magnetic) and click then on the two bounding lines.

There are two modes for creating more complex general path objects. The difference between line mode and polygon mode is that the first creates an open path, the latter generates a closed one. As a consequence, the line mode uses the current arrow settings, while the polygon mode doesn't. The path object created using line or polygon mode consists of segments of various types. The initial setting is to create straight segments. By holding the shift-key when pressing the left mouse button one can switch to uniform B-splines. One can also add quadratic Bézier spline segments, cubic Bézier spline segments, and circular arc segments as follows:

To add a quadratic Bézier spline (that is, a parabola), click twice in polyline mode for the first two control points. Then press the q key and click on the third (last) control point.

Similarly, to add a cubic Bézier spline, click three times in polyline mode on the first three control points. Press the c key, and click on the last control point.

Circular arcs can be added as follows: Click twice in polyline mode, once on the starting point of the arc, then on a point in the correct tangent direction. Press the a key, and click on the endpoint of the arc.

To make curves where segments of different type are joined with identical tangents, you can press the y key whenever you are starting a new segment: this will set the coordinate system centered at the starting point of the segment, and aligned with the tangent to the previous segment.

For the mathematically inclined, a more precise description of the segments that can appear on a subpath follows. More details can be found in Foley et al.2 and other text books on splines.

A subpath consists of a sequence of segments. Each segment is either a straight line segment, an elliptic arc, a quadratic Bézier spline, a cubic Bézier spline, or a uniform cubic B-spline.

The quadratic Bézier spline defined by control points p0, p1, and p2, is the curve

P(t) = (1-t)2 p0 + 2t(1-t) p1 + t2 p2,
where t ranges from 0 to 1. This implies that it starts in p0 tangent to the line p0p1, ends in p2 tangent to the line p1p2, and is contained in the convex hull of the three points. Any segment of any parabola can be expressed as a quadratic Bézier spline.

For instance, the piece of the unit parabola y = x2 between x=a and x=b can be created with the control points

p0 = (a, a2)
p1 = ( (a + b)/(2), ab)
p2 = (b, b2)
Any piece of any parabola can be created by applying some affine transformation to these points.

The cubic Bézier spline with control points p0, p1, p2, and p3 is the curve

R(t) = (1-t)3p0 + 3t(1-t)2 p1 + 3 t2(1-t) p2 + t3 p3.
It starts in p0 being tangent to the line p0p1, ends in p3 being tangent to the line p2p3, and lies in the convex hull of the four control points.

Uniform cubic B-splines approximate a series of m+1 control points p0, p1, …, pm, m ≥ 3, with a curve consisting of m-2 cubic polynomial curve segments s0, s1, …, sm-3. Every such curve segment is defined by four of the control points. In fact, curve segment si is defined by the points pi, pi+1, pi+2, and pi+3. If the curve is closed (a splinegon), it contains three additional curve segments sm-2, sm-1, and sm, defined by appending p0, p1, and p2 to the end of the sequence. A uniform B-spline segment on an open subpath of an Ipe path object is defined by repeating both the first and last control point three times, so as to make the segment begin and end in these points.

The segment si is the cubic curve segment with the following parametrization.

Q(t) = ((1-t)3)/(6) pi + (3t3 -6t2 + 4)/(6) pi+1 + (-3t3 + 3t2 + 3t +1)/(6) pi+2 + (t3)/(6) pi+3,
where t ranges from 0 to 1.

Since the point Q(t) is a convex combination of the four control points, the curve segment si lies in the convex hull of pi to pi+3. Furthermore, it follows that any affine transformation can be applied to the curve by applying it to the control points. Note that a control point pi has influence on only four curve segments, si-3, si-2, si-1, and si. Thus, when you edit a spline object and move a control point, only a short piece of the spline in the neighborhood of the control point will move.

ipe-7.1.4/build/doc/classipe_1_1_pdf_string-members.html0000644000175000017500000001353612120621776023032 0ustar otfriedotfried Ipelib: Member List
ipe::PdfString Member List

This is the complete list of members for ipe::PdfString, including all inherited members.

array() const ipe::PdfObjvirtual
boolean() const ipe::PdfObjvirtual
dict() const ipe::PdfObjvirtual
name() const ipe::PdfObjvirtual
null() const ipe::PdfObjvirtual
number() const ipe::PdfObjvirtual
PdfString(const String &val)ipe::PdfStringinlineexplicit
ref() const ipe::PdfObjvirtual
repr() const ipe::PdfObj
string() const ipe::PdfStringvirtual
value() const ipe::PdfStringinline
write(Stream &stream) const ipe::PdfStringvirtual
~PdfObj()=0ipe::PdfObjpure virtual

ipe-7.1.4/build/doc/doxygen.css0000644000175000017500000004705012120621776016217 0ustar otfriedotfried/* The standard CSS for doxygen */ body, table, div, p, dl { font: 400 14px/19px Roboto,sans-serif; } /* @group Heading Levels */ h1 { font-size: 150%; } .title { font-size: 150%; font-weight: bold; margin: 10px 2px; } h2 { border-bottom: 1px solid #879ECB; color: #354C7B; font-size: 150%; font-weight: normal; margin-top: 1.75em; padding-top: 8px; padding-bottom: 4px; width: 100%; } h3 { font-size: 100%; } h1, h2, h3, h4, h5, h6 { -webkit-transition: text-shadow 0.5s linear; -moz-transition: text-shadow 0.5s linear; -ms-transition: text-shadow 0.5s linear; -o-transition: text-shadow 0.5s linear; transition: text-shadow 0.5s linear; margin-right: 15px; } h1.glow, h2.glow, h3.glow, h4.glow, h5.glow, h6.glow { text-shadow: 0 0 15px cyan; } dt { font-weight: bold; } div.multicol { -moz-column-gap: 1em; -webkit-column-gap: 1em; -moz-column-count: 3; -webkit-column-count: 3; } p.startli, p.startdd, p.starttd { margin-top: 2px; } p.endli { margin-bottom: 0px; } p.enddd { margin-bottom: 4px; } p.endtd { margin-bottom: 2px; } /* @end */ caption { font-weight: bold; } span.legend { font-size: 70%; text-align: center; } h3.version { font-size: 90%; text-align: center; } div.qindex, div.navtab{ background-color: #EBEFF6; border: 1px solid #A3B4D7; text-align: center; } div.qindex, div.navpath { width: 100%; line-height: 140%; } div.navtab { margin-right: 15px; } /* @group Link Styling */ a { color: #3D578C; font-weight: normal; text-decoration: none; } .contents a:visited { color: #4665A2; } a:hover { text-decoration: underline; } a.qindex { font-weight: bold; } a.qindexHL { font-weight: bold; background-color: #9CAFD4; color: #ffffff; border: 1px double #869DCA; } .contents a.qindexHL:visited { color: #ffffff; } a.el { font-weight: bold; } a.elRef { } a.code, a.code:visited { color: #4665A2; } a.codeRef, a.codeRef:visited { color: #4665A2; } /* @end */ dl.el { margin-left: -1cm; } pre.fragment { border: 1px solid #C4CFE5; background-color: #FBFCFD; padding: 4px 6px; margin: 4px 8px 4px 2px; overflow: auto; word-wrap: break-word; font-size: 9pt; line-height: 125%; font-family: monospace, fixed; font-size: 105%; } div.fragment { padding: 4px; margin: 4px; background-color: #FBFCFD; border: 1px solid #C4CFE5; } div.line { font-family: monospace, fixed; font-size: 13px; min-height: 13px; line-height: 1.0; text-wrap: unrestricted; white-space: -moz-pre-wrap; /* Moz */ white-space: -pre-wrap; /* Opera 4-6 */ white-space: -o-pre-wrap; /* Opera 7 */ white-space: pre-wrap; /* CSS3 */ word-wrap: break-word; /* IE 5.5+ */ text-indent: -53px; padding-left: 53px; padding-bottom: 0px; margin: 0px; -webkit-transition-property: background-color, box-shadow; -webkit-transition-duration: 0.5s; -moz-transition-property: background-color, box-shadow; -moz-transition-duration: 0.5s; -ms-transition-property: background-color, box-shadow; -ms-transition-duration: 0.5s; -o-transition-property: background-color, box-shadow; -o-transition-duration: 0.5s; transition-property: background-color, box-shadow; transition-duration: 0.5s; } div.line.glow { background-color: cyan; box-shadow: 0 0 10px cyan; } span.lineno { padding-right: 4px; text-align: right; border-right: 2px solid #0F0; background-color: #E8E8E8; white-space: pre; } span.lineno a { background-color: #D8D8D8; } span.lineno a:hover { background-color: #C8C8C8; } div.ah { background-color: black; font-weight: bold; color: #ffffff; margin-bottom: 3px; margin-top: 3px; padding: 0.2em; border: solid thin #333; border-radius: 0.5em; -webkit-border-radius: .5em; -moz-border-radius: .5em; box-shadow: 2px 2px 3px #999; -webkit-box-shadow: 2px 2px 3px #999; -moz-box-shadow: rgba(0, 0, 0, 0.15) 2px 2px 2px; background-image: -webkit-gradient(linear, left top, left bottom, from(#eee), to(#000),color-stop(0.3, #444)); background-image: -moz-linear-gradient(center top, #eee 0%, #444 40%, #000); } div.groupHeader { margin-left: 16px; margin-top: 12px; font-weight: bold; } div.groupText { margin-left: 16px; font-style: italic; } body { background-color: white; color: black; margin: 0; } div.contents { margin-top: 10px; margin-left: 12px; margin-right: 8px; } td.indexkey { background-color: #EBEFF6; font-weight: bold; border: 1px solid #C4CFE5; margin: 2px 0px 2px 0; padding: 2px 10px; white-space: nowrap; vertical-align: top; } td.indexvalue { background-color: #EBEFF6; border: 1px solid #C4CFE5; padding: 2px 10px; margin: 2px 0px; } tr.memlist { background-color: #EEF1F7; } p.formulaDsp { text-align: center; } img.formulaDsp { } img.formulaInl { vertical-align: middle; } div.center { text-align: center; margin-top: 0px; margin-bottom: 0px; padding: 0px; } div.center img { border: 0px; } address.footer { text-align: right; padding-right: 12px; } img.footer { border: 0px; vertical-align: middle; } /* @group Code Colorization */ span.keyword { color: #008000 } span.keywordtype { color: #604020 } span.keywordflow { color: #e08000 } span.comment { color: #800000 } span.preprocessor { color: #806020 } span.stringliteral { color: #002080 } span.charliteral { color: #008080 } span.vhdldigit { color: #ff00ff } span.vhdlchar { color: #000000 } span.vhdlkeyword { color: #700070 } span.vhdllogic { color: #ff0000 } blockquote { background-color: #F7F8FB; border-left: 2px solid #9CAFD4; margin: 0 24px 0 4px; padding: 0 12px 0 16px; } /* @end */ /* .search { color: #003399; font-weight: bold; } form.search { margin-bottom: 0px; margin-top: 0px; } input.search { font-size: 75%; color: #000080; font-weight: normal; background-color: #e8eef2; } */ td.tiny { font-size: 75%; } .dirtab { padding: 4px; border-collapse: collapse; border: 1px solid #A3B4D7; } th.dirtab { background: #EBEFF6; font-weight: bold; } hr { height: 0px; border: none; border-top: 1px solid #4A6AAA; } hr.footer { height: 1px; } /* @group Member Descriptions */ table.memberdecls { border-spacing: 0px; padding: 0px; } .memberdecls td, .fieldtable tr { -webkit-transition-property: background-color, box-shadow; -webkit-transition-duration: 0.5s; -moz-transition-property: background-color, box-shadow; -moz-transition-duration: 0.5s; -ms-transition-property: background-color, box-shadow; -ms-transition-duration: 0.5s; -o-transition-property: background-color, box-shadow; -o-transition-duration: 0.5s; transition-property: background-color, box-shadow; transition-duration: 0.5s; } .memberdecls td.glow, .fieldtable tr.glow { background-color: cyan; box-shadow: 0 0 15px cyan; } .mdescLeft, .mdescRight, .memItemLeft, .memItemRight, .memTemplItemLeft, .memTemplItemRight, .memTemplParams { background-color: #F9FAFC; border: none; margin: 4px; padding: 1px 0 0 8px; } .mdescLeft, .mdescRight { padding: 0px 8px 4px 8px; color: #555; } .memItemLeft, .memItemRight, .memTemplParams { border-bottom: 1px solid #DEE4F0; } .memItemLeft, .memTemplItemLeft { white-space: nowrap; } .memItemRight { width: 100%; } .memTemplParams { color: #4665A2; white-space: nowrap; } /* @end */ /* @group Member Details */ /* Styles for detailed member documentation */ .memtemplate { font-size: 80%; color: #4665A2; font-weight: normal; margin-left: 9px; } .memnav { background-color: #EBEFF6; border: 1px solid #A3B4D7; text-align: center; margin: 2px; margin-right: 15px; padding: 2px; } .mempage { width: 100%; } .memitem { padding: 0; margin-bottom: 10px; margin-right: 5px; -webkit-transition: box-shadow 0.5s linear; -moz-transition: box-shadow 0.5s linear; -ms-transition: box-shadow 0.5s linear; -o-transition: box-shadow 0.5s linear; transition: box-shadow 0.5s linear; display: table !important; width: 100%; } .memitem.glow { box-shadow: 0 0 15px cyan; } .memname { font-weight: bold; margin-left: 6px; } .memname td { vertical-align: bottom; } .memproto, dl.reflist dt { border-top: 1px solid #A8B8D9; border-left: 1px solid #A8B8D9; border-right: 1px solid #A8B8D9; padding: 6px 0px 6px 0px; color: #253555; font-weight: bold; text-shadow: 0px 1px 1px rgba(255, 255, 255, 0.9); background-image:url('nav_f.png'); background-repeat:repeat-x; background-color: #E2E8F2; /* opera specific markup */ box-shadow: 5px 5px 5px rgba(0, 0, 0, 0.15); border-top-right-radius: 4px; border-top-left-radius: 4px; /* firefox specific markup */ -moz-box-shadow: rgba(0, 0, 0, 0.15) 5px 5px 5px; -moz-border-radius-topright: 4px; -moz-border-radius-topleft: 4px; /* webkit specific markup */ -webkit-box-shadow: 5px 5px 5px rgba(0, 0, 0, 0.15); -webkit-border-top-right-radius: 4px; -webkit-border-top-left-radius: 4px; } .memdoc, dl.reflist dd { border-bottom: 1px solid #A8B8D9; border-left: 1px solid #A8B8D9; border-right: 1px solid #A8B8D9; padding: 6px 10px 2px 10px; background-color: #FBFCFD; border-top-width: 0; background-image:url('nav_g.png'); background-repeat:repeat-x; background-color: #FFFFFF; /* opera specific markup */ border-bottom-left-radius: 4px; border-bottom-right-radius: 4px; box-shadow: 5px 5px 5px rgba(0, 0, 0, 0.15); /* firefox specific markup */ -moz-border-radius-bottomleft: 4px; -moz-border-radius-bottomright: 4px; -moz-box-shadow: rgba(0, 0, 0, 0.15) 5px 5px 5px; /* webkit specific markup */ -webkit-border-bottom-left-radius: 4px; -webkit-border-bottom-right-radius: 4px; -webkit-box-shadow: 5px 5px 5px rgba(0, 0, 0, 0.15); } dl.reflist dt { padding: 5px; } dl.reflist dd { margin: 0px 0px 10px 0px; padding: 5px; } .paramkey { text-align: right; } .paramtype { white-space: nowrap; } .paramname { color: #602020; white-space: nowrap; } .paramname em { font-style: normal; } .paramname code { line-height: 14px; } .params, .retval, .exception, .tparams { margin-left: 0px; padding-left: 0px; } .params .paramname, .retval .paramname { font-weight: bold; vertical-align: top; } .params .paramtype { font-style: italic; vertical-align: top; } .params .paramdir { font-family: "courier new",courier,monospace; vertical-align: top; } table.mlabels { border-spacing: 0px; } td.mlabels-left { width: 100%; padding: 0px; } td.mlabels-right { vertical-align: bottom; padding: 0px; white-space: nowrap; } span.mlabels { margin-left: 8px; } span.mlabel { background-color: #728DC1; border-top:1px solid #5373B4; border-left:1px solid #5373B4; border-right:1px solid #C4CFE5; border-bottom:1px solid #C4CFE5; text-shadow: none; color: white; margin-right: 4px; padding: 2px 3px; border-radius: 3px; font-size: 7pt; white-space: nowrap; } /* @end */ /* these are for tree view when not used as main index */ div.directory { margin: 10px 0px; border-top: 1px solid #A8B8D9; border-bottom: 1px solid #A8B8D9; width: 100%; } .directory table { border-collapse:collapse; } .directory td { margin: 0px; padding: 0px; vertical-align: top; } .directory td.entry { white-space: nowrap; padding-right: 6px; } .directory td.entry a { outline:none; } .directory td.entry a img { border: none; } .directory td.desc { width: 100%; padding-left: 6px; padding-right: 6px; padding-top: 3px; border-left: 1px solid rgba(0,0,0,0.05); } .directory tr.even { padding-left: 6px; background-color: #F7F8FB; } .directory img { vertical-align: -30%; } .directory .levels { white-space: nowrap; width: 100%; text-align: right; font-size: 9pt; } .directory .levels span { cursor: pointer; padding-left: 2px; padding-right: 2px; color: #3D578C; } div.dynheader { margin-top: 8px; -webkit-touch-callout: none; -webkit-user-select: none; -khtml-user-select: none; -moz-user-select: none; -ms-user-select: none; user-select: none; } address { font-style: normal; color: #2A3D61; } table.doxtable { border-collapse:collapse; margin-top: 4px; margin-bottom: 4px; } table.doxtable td, table.doxtable th { border: 1px solid #2D4068; padding: 3px 7px 2px; } table.doxtable th { background-color: #374F7F; color: #FFFFFF; font-size: 110%; padding-bottom: 4px; padding-top: 5px; } table.fieldtable { width: 100%; margin-bottom: 10px; border: 1px solid #A8B8D9; border-spacing: 0px; -moz-border-radius: 4px; -webkit-border-radius: 4px; border-radius: 4px; -moz-box-shadow: rgba(0, 0, 0, 0.15) 2px 2px 2px; -webkit-box-shadow: 2px 2px 2px rgba(0, 0, 0, 0.15); box-shadow: 2px 2px 2px rgba(0, 0, 0, 0.15); } .fieldtable td, .fieldtable th { padding: 3px 7px 2px; } .fieldtable td.fieldtype, .fieldtable td.fieldname { white-space: nowrap; border-right: 1px solid #A8B8D9; border-bottom: 1px solid #A8B8D9; vertical-align: top; } .fieldtable td.fielddoc { border-bottom: 1px solid #A8B8D9; width: 100%; } .fieldtable tr:last-child td { border-bottom: none; } .fieldtable th { background-image:url('nav_f.png'); background-repeat:repeat-x; background-color: #E2E8F2; font-size: 90%; color: #253555; padding-bottom: 4px; padding-top: 5px; text-align:left; -moz-border-radius-topleft: 4px; -moz-border-radius-topright: 4px; -webkit-border-top-left-radius: 4px; -webkit-border-top-right-radius: 4px; border-top-left-radius: 4px; border-top-right-radius: 4px; border-bottom: 1px solid #A8B8D9; } .tabsearch { top: 0px; left: 10px; height: 36px; background-image: url('tab_b.png'); z-index: 101; overflow: hidden; font-size: 13px; } .navpath ul { font-size: 11px; background-image:url('tab_b.png'); background-repeat:repeat-x; height:30px; line-height:30px; color:#8AA0CC; border:solid 1px #C2CDE4; overflow:hidden; margin:0px; padding:0px; } .navpath li { list-style-type:none; float:left; padding-left:10px; padding-right:15px; background-image:url('bc_s.png'); background-repeat:no-repeat; background-position:right; color:#364D7C; } .navpath li.navelem a { height:32px; display:block; text-decoration: none; outline: none; font-family: 'Lucida Grande',Geneva,Helvetica,Arial,sans-serif; } .navpath li.navelem a:hover { color:#6884BD; } .navpath li.footer { list-style-type:none; float:right; padding-left:10px; padding-right:15px; background-image:none; background-repeat:no-repeat; background-position:right; color:#364D7C; font-size: 8pt; } div.summary { float: right; font-size: 8pt; padding-right: 5px; width: 50%; text-align: right; } div.summary a { white-space: nowrap; } div.ingroups { font-size: 8pt; width: 50%; text-align: left; } div.ingroups a { white-space: nowrap; } div.header { background-image:url('nav_h.png'); background-repeat:repeat-x; background-color: #F9FAFC; margin: 0px; border-bottom: 1px solid #C4CFE5; } div.headertitle { padding: 5px 5px 5px 10px; } dl { padding: 0 0 0 10px; } /* dl.note, dl.warning, dl.attention, dl.pre, dl.post, dl.invariant, dl.deprecated, dl.todo, dl.test, dl.bug */ dl.section { margin-left: 0px; padding-left: 0px; } dl.note { margin-left:-7px; padding-left: 3px; border-left:4px solid; border-color: #D0C000; } dl.warning, dl.attention { margin-left:-7px; padding-left: 3px; border-left:4px solid; border-color: #FF0000; } dl.pre, dl.post, dl.invariant { margin-left:-7px; padding-left: 3px; border-left:4px solid; border-color: #00D000; } dl.deprecated { margin-left:-7px; padding-left: 3px; border-left:4px solid; border-color: #505050; } dl.todo { margin-left:-7px; padding-left: 3px; border-left:4px solid; border-color: #00C0E0; } dl.test { margin-left:-7px; padding-left: 3px; border-left:4px solid; border-color: #3030E0; } dl.bug { margin-left:-7px; padding-left: 3px; border-left:4px solid; border-color: #C08050; } dl.section dd { margin-bottom: 6px; } #projectlogo { text-align: center; vertical-align: bottom; border-collapse: separate; } #projectlogo img { border: 0px none; } #projectname { font: 300% Tahoma, Arial,sans-serif; margin: 0px; padding: 2px 0px; } #projectbrief { font: 120% Tahoma, Arial,sans-serif; margin: 0px; padding: 0px; } #projectnumber { font: 50% Tahoma, Arial,sans-serif; margin: 0px; padding: 0px; } #titlearea { padding: 0px; margin: 0px; width: 100%; border-bottom: 1px solid #5373B4; } .image { text-align: center; } .dotgraph { text-align: center; } .mscgraph { text-align: center; } .caption { font-weight: bold; } div.zoom { border: 1px solid #90A5CE; } dl.citelist { margin-bottom:50px; } dl.citelist dt { color:#334975; float:left; font-weight:bold; margin-right:10px; padding:5px; } dl.citelist dd { margin:2px 0; padding:5px 0; } div.toc { padding: 14px 25px; background-color: #F4F6FA; border: 1px solid #D8DFEE; border-radius: 7px 7px 7px 7px; float: right; height: auto; margin: 0 20px 10px 10px; width: 200px; } div.toc li { background: url("bdwn.png") no-repeat scroll 0 5px transparent; font: 10px/1.2 Verdana,DejaVu Sans,Geneva,sans-serif; margin-top: 5px; padding-left: 10px; padding-top: 2px; } div.toc h3 { font: bold 12px/1.2 Arial,FreeSans,sans-serif; color: #4665A2; border-bottom: 0 none; margin: 0; } div.toc ul { list-style: none outside none; border: medium none; padding: 0px; } div.toc li.level1 { margin-left: 0px; } div.toc li.level2 { margin-left: 15px; } div.toc li.level3 { margin-left: 30px; } div.toc li.level4 { margin-left: 45px; } .inherit_header { font-weight: bold; color: gray; cursor: pointer; -webkit-touch-callout: none; -webkit-user-select: none; -khtml-user-select: none; -moz-user-select: none; -ms-user-select: none; user-select: none; } .inherit_header td { padding: 6px 0px 2px 5px; } .inherit { display: none; } tr.heading h2 { margin-top: 12px; margin-bottom: 4px; } @media print { #top { display: none; } #side-nav { display: none; } #nav-path { display: none; } body { overflow:visible; } h1, h2, h3, h4, h5, h6 { page-break-after: avoid; } .summary { display: none; } .memitem { page-break-inside: avoid; } #doc-content { margin-left:0 !important; height:auto !important; width:auto !important; overflow:inherit; display:inline; } } ipe-7.1.4/build/doc/manual_20.html0000644000175000017500000001036312120621776016471 0ustar otfriedotfried Ipe Manual -- 4.5 Reference objects and symbols
4 Object types4.4 Group objects4.5 Reference objects and symbols

4.5 Reference objects and symbols

A symbol is a single Ipe object (which can of course be a group) that is defined in a document's stylesheet. A reference object is a reference to a symbol, placed at a given position on the page.

Symbols can be parameterized with stroke and fill color, pen width, and symbol size. Whether or not a symbol accepts which parameter is visible from the symbol's name: if it takes any parameter, the name must end in a pair of parentheses containing some of the letters "s", "f", "p", "x" (in this order), for the parameters stroke, fill, pen, and size. References to parameterized symbols allow all the attributes that the symbol accepts.

All references can be translated around the page. Whether or not the symbol can be rotated or stretched depends on the definition of the symbol in the stylesheet.

If a symbol named "Background" exists in your stylesheet, it is automatically displayed on each page, at the very back. To suppress the automatic display, create a layer named "BACKGROUND" on the page, and set it to be invisible. Note that the background symbol is not shown in Postscript output!

Marks are symbols with special support from the Ipe user interface. They are used to mark points in the drawing, and come in several different looks (little circles, discs, squares, boxes, or crosses). You can define your own mark shapes by defining appropriate symbols in your stylesheet.

Note that marks behave quite different from path objects. In particular, you should not confuse a disc mark with a little disc created as a circle object:

  • a solid mark (type disk and square) only obeys the stroke color (but fdisk and fsquare marks are filled with the fill color)
  • when you scale a mark, it will not change its size (you can change the mark size from the properties panel, though)
  • when you rotate a mark, it does not change its orientation
You can change a mark's shape and size later.
ipe-7.1.4/build/doc/manual.css0000644000175000017500000000066612120621776016021 0ustar otfriedotfriedbody, table, div, p { font-family: Georgia, serif; } h1 { font-family: Lucida Grande, Verdana, Geneva, Arial, sans-serif; color: #153788; text-align: left; } h2 { font-family: Lucida Grande, Verdana, Geneva, Arial, sans-serif; color: #153788; text-align: left; } h3 { font-family: Lucida Grande, Verdana, Geneva, Arial, sans-serif; color: #153788; text-align: left; } em { color: #FF9900; }ipe-7.1.4/build/doc/radgrad2.svg0000644000175000017500000000234612120621776016236 0ustar otfriedotfried ipe-7.1.4/build/doc/classipe_1_1_latex-members.html0000644000175000017500000001067112120621776022005 0ustar otfriedotfried Ipelib: Member List
ipe::Latex Member List

This is the complete list of members for ipe::Latex, including all inherited members.

createLatexSource(Stream &stream, String preamble)ipe::Latex
ipe::TextCollectingVisitor classipe::Latexfriend
Latex(const Cascade *sheet)ipe::Latex
readPdf(DataSource &source)ipe::Latex
scanObject(const Object *obj)ipe::Latex
scanPage(Page *page)ipe::Latex
takeFontPool()ipe::Latex
updateTextObjects()ipe::Latex
~Latex()ipe::Latex

ipe-7.1.4/build/doc/structipe_1_1_gradient-members.html0000644000175000017500000001066712120621776022711 0ustar otfriedotfried Ipelib: Member List
ipe::Gradient Member List

ipe-7.1.4/build/doc/functions_0x72.html0000644000175000017500000001735712120621776017515 0ustar otfriedotfried Ipelib: Class Members
Here is a list of all class members with links to the classes they belong to:

- r -


ipe-7.1.4/build/doc/tab_h.png0000644000175000017500000000030012120621776015576 0ustar otfriedotfried‰PNG  IHDR$ÇÇ[‡IDATxíÝË ‚@EÑ 7êÂX’Ñø AADùjGü€ Z€e؈£ ë8¹›—Wƒx¾ÞìUK.µ%„0mɤ&+4iÑ$džÈt“׿ÍzWf5AZá'w¼øÆ"2¶Wœðòg%öªdæ)æþ™ÉR15F®dìž ÉБßO«×Áô»C"à@¯g=IEND®B`‚ipe-7.1.4/build/doc/classipe_1_1_pdf_file.html0000644000175000017500000001660312120621776021011 0ustar otfriedotfried Ipelib: ipe::PdfFile Class Reference
ipe::PdfFile Class Reference

#include <ipepdfparser.h>

Public Member Functions

 PdfFile ()
 ~PdfFile ()
bool parse (DataSource &source)
const PdfObjobject (int num) const
const PdfDictcatalog () const
const PdfDictpage () const

Detailed Description

All information obtained by parsing a PDF file.

Constructor & Destructor Documentation

PdfFile::PdfFile ( )

Create empty container.

PdfFile::~PdfFile ( )

Member Function Documentation

bool PdfFile::parse ( DataSource source)

Parse entire PDF stream, and store objects.

const PdfObj * PdfFile::object ( int  num) const

Return object with number num.

const PdfDict * PdfFile::catalog ( ) const

Return root catalog of PDF file.

const PdfDict * PdfFile::page ( ) const

Return first page of the document.


The documentation for this class was generated from the following files:
  • ipepdfparser.h
  • ipepdfparser.cpp

ipe-7.1.4/build/doc/group__cairo.html0000644000175000017500000000635312120621776017367 0ustar otfriedotfried Ipelib: Ipe Cairo interface
Ipe Cairo interface

Classes

class  ipe::CairoPainter
 Ipe Painter using Cairo and Freetype as a backend. More...
class  ipe::Fonts
 Provides the fonts used to render text. More...
class  ipe::Face
 A typeface (aka font), actually loaded (from a font file or PDF file). More...

Detailed Description

Drawing Ipe objects using the Cairo library.

This module contains the classes needed to render Ipe objects using the Cairo and Freetype libraries.

These classes are not in Ipelib, but in a separate library libipecairo.


ipe-7.1.4/build/doc/classipe_1_1_page.html0000644000175000017500000022773712120621776020171 0ustar otfriedotfried Ipelib: ipe::Page Class Reference

#include <ipepage.h>

Classes

struct  SLayer
struct  SObject
struct  SView

Public Member Functions

 Page ()
void saveAsXml (Stream &stream) const
void saveAsIpePage (Stream &stream) const
void saveSelection (Stream &stream) const
int countLayers () const
String layer (int index) const
bool isLocked (int i) const
bool hasSnapping (int i) const
void setLocked (int i, bool flag)
void setSnapping (int i, bool flag)
void moveLayer (int index, int newIndex)
int findLayer (String name) const
void addLayer (String name)
void addLayer ()
void removeLayer (String name)
void renameLayer (String oldName, String newName)
int countViews () const
int countMarkedViews () const
Attribute effect (int index) const
void setEffect (int index, Attribute sym)
String active (int index) const
void setActive (int index, String name)
bool markedView (int index) const
void setMarkedView (int index, bool marked)
void insertView (int i, String active)
void removeView (int i)
void clearViews ()
bool visible (int view, int layer) const
bool objectVisible (int view, int objno) const
void setVisible (int view, String layer, bool vis)
Rect textBox (const Cascade *sheet) const
String title () const
void setTitle (String title)
String section (int level) const
void setSection (int level, bool useTitle, String name)
bool sectionUsesTitle (int level) const
const TexttitleText () const
void applyTitleStyle (const Cascade *sheet)
bool marked () const
void setMarked (bool marked)
String notes () const
void setNotes (String notes)
int count () const
Objectobject (int i)
const Objectobject (int i) const
TSelect select (int i) const
int layerOf (int i) const
void setSelect (int i, TSelect sel)
void setLayerOf (int i, int layer)
Rect pageBBox (const Cascade *sheet) const
Rect viewBBox (const Cascade *sheet, int view) const
Rect bbox (int i) const
void transform (int i, const Matrix &m)
double distance (int i, const Vector &v, double bound) const
void snapVtx (int i, const Vector &mouse, Vector &pos, double &bound) const
void snapBnd (int i, const Vector &mouse, Vector &pos, double &bound) const
void invalidateBBox (int i) const
void insert (int i, TSelect sel, int layer, Object *obj)
void append (TSelect sel, int layer, Object *obj)
void remove (int i)
void replace (int i, Object *obj)
bool setAttribute (int i, Property prop, Attribute value, Attribute stroke, Attribute fill)
int primarySelection () const
bool hasSelection () const
void deselectAll ()
void ensurePrimarySelection ()

Static Public Member Functions

static Pagebasic ()

Detailed Description

An Ipe document page.

Its main ingredients are a sequence of Objects (with selection state, layer, and a cached bounding box), a set of Layers, and a sequence of Views.

Each object on a Page belongs to one of the layers of the page. Layers are orthogonal to the back-to-front ordering of objects (in particular, they are not "layered" - the word is a misnomer). The "layer" is really just another attribute of the object.

  • Layers are either editable or locked. Objects in a locked layer cannot be selected, and a locked layer cannot be made active in the UI. This more or less means that the contents of such a layer cannot be modified—but that's a consequence of the UI, Ipelib contains no special handling of locked layers.
  • A layer may have snapping on or off—objects will behave magnetically only if their layer has snapping on.

A Page is presented in a number of views. Each view presents some of the layers of the page. In addition, each view has an active layer (where objects are added when this view is shown in the UI), and possibly a transition effect (Acrobat Reader eye candy).

A Page can be copied and assigned. The operation takes time linear in the number of top-level object on the page.

Constructor & Destructor Documentation

Page::Page ( )
explicit

The default constructor creates a new empty page.

This page still needs a layer and a view to be usable!

Member Function Documentation

Page * Page::basic ( )
static

Create a new empty page with standard settings.

This is an empty page with layer 'alpha' and a single view.

void Page::saveAsXml ( Stream stream) const

save page in XML format.

void Page::saveAsIpePage ( Stream stream) const

Copy whole page with bitmaps as <ipepage> into the stream.

void Page::saveSelection ( Stream stream) const

Copy selected objects as <ipeselection> into the stream.

int ipe::Page::countLayers ( ) const
inline

Return number of layers.

String ipe::Page::layer ( int  index) const
inline

Return name of layer index.

bool ipe::Page::isLocked ( int  i) const
inline

Is layer i locked?

bool ipe::Page::hasSnapping ( int  i) const
inline

Does layer i have active snapping?

void Page::setLocked ( int  i,
bool  flag 
)

Set locking of layer i.

void Page::setSnapping ( int  i,
bool  flag 
)

Set snapping of layer i.

void Page::moveLayer ( int  index,
int  newIndex 
)

Moves the position of a layer in the layer list.

int Page::findLayer ( String  name) const

Find layer with given name.

Returns -1 if not found.

void Page::addLayer ( String  name)

Add a new layer.

void Page::addLayer ( )

Add a new layer with unique name.

void Page::removeLayer ( String  name)

Removes an empty layer from the page.

All objects are adjusted. Panics if there are objects in the deleted layer, of if it is the only layer.

void Page::renameLayer ( String  oldName,
String  newName 
)

Rename a layer.

int ipe::Page::countViews ( ) const
inline

Return number of views.

int Page::countMarkedViews ( ) const
Attribute ipe::Page::effect ( int  index) const
inline

Return effect of view.

void Page::setEffect ( int  index,
Attribute  sym 
)

Set effect of view.

Panics if sym is not symbolic.

String ipe::Page::active ( int  index) const
inline

Return active layer of view.

void Page::setActive ( int  index,
String  name 
)

Set active layer of view.

bool ipe::Page::markedView ( int  index) const
inline

Return if view is marked.

void Page::setMarkedView ( int  index,
bool  marked 
)

Set if view is marked.

void Page::insertView ( int  i,
String  active 
)

Insert a new view at index i.

void Page::removeView ( int  i)

Remove the view at index i.

void Page::clearViews ( )

Remove all views of this page.

bool ipe::Page::visible ( int  view,
int  layer 
) const
inline

Is layer visible in view?

bool ipe::Page::objectVisible ( int  view,
int  objno 
) const
inline

Is object at index objno visible in view?

void Page::setVisible ( int  view,
String  layer,
bool  vis 
)

Set visibility of layer layer in view view.

Rect Page::textBox ( const Cascade sheet) const

Computes text box.

Takes into account frame size and text objects already on the page .

String Page::title ( ) const

Return title of this page.

void Page::setTitle ( String  title)

Set the title of this page.

An empty title is not displayed.

String Page::section ( int  level) const

Return section title at level.

Level 0 is the section, level 1 the subsection.

void Page::setSection ( int  level,
bool  useTitle,
String  name 
)

Set the section title at level.

Level 0 is the section, level 1 the subsection.

If useTitle is true, then name is ignored, and the section title will be copied from the page title (and further changes to the page title are automatically reflected).

bool ipe::Page::sectionUsesTitle ( int  level) const
inline

Does this section title reflect the page title?

const Text * Page::titleText ( ) const

Return Text object representing the title text.

Return 0 if no title is set. Ownership of object remains with Page.

void Page::applyTitleStyle ( const Cascade sheet)

Apply styling to title text object.

bool ipe::Page::marked ( ) const
inline

Return if page is marked for printing.

void Page::setMarked ( bool  marked)

Set if page is marked for printing.

String ipe::Page::notes ( ) const
inline

Return notes for this page.

void Page::setNotes ( String  notes)

Set the notes of this page.

int ipe::Page::count ( ) const
inline

Return number of objects on the page.

Object* ipe::Page::object ( int  i)
inline

Return object at index i.

const Object* ipe::Page::object ( int  i) const
inline

Return object at index i (const version).

TSelect ipe::Page::select ( int  i) const
inline

Return selection status of object at index i.

int ipe::Page::layerOf ( int  i) const
inline

Return layer of object at index i.

void ipe::Page::setSelect ( int  i,
TSelect  sel 
)
inline

Set selection status of object at index i.

void ipe::Page::setLayerOf ( int  i,
int  layer 
)
inline

Set layer of object at index i.

Rect Page::pageBBox ( const Cascade sheet) const

Returns a precise bounding box for the artwork on the page.

This is meant to be used as the bounding box in PDF and EPS output. It is computed by rendering all objects on the page that are visible in at least one view, plus all objects in a layer named "BBOX" (even if that is not visible), using a BBoxPainter.

Rect Page::viewBBox ( const Cascade sheet,
int  view 
) const

Returns a precise bounding box for the artwork in the view.

This is meant to be used as the bounding box in PDF and EPS output. It is computed by rendering all objects in the page using a BBoxPainter.

Rect Page::bbox ( int  i) const

Return a bounding box for the object at index i.

This is a bounding box including the control points of the object. If you need a tight bounding box, you'll need to use the Object directly.

The Page caches the box the first time it is computed.

Make sure you call Page::transform instead of Object::setMatrix, as the latter would not invalidate the bounding box.

void Page::transform ( int  i,
const Matrix m 
)

Transform the object at index i.

Use this function instead of calling Object::setMatrix directly, as the latter doesn't invalidate the cached bounding box.

double Page::distance ( int  i,
const Vector v,
double  bound 
) const

Return distance between object at index i and v.

But may just return bound if the distance is larger. This function uses the cached bounded box, and is faster than calling Object::distance directly.

void Page::snapVtx ( int  i,
const Vector mouse,
Vector pos,
double &  bound 
) const

Compute possible vertex snapping position for object at index i.

Looks only for positions closer than bound. If successful, modifies pos and bound.

void Page::snapBnd ( int  i,
const Vector mouse,
Vector pos,
double &  bound 
) const

Compute possible boundary snapping position for object at index i.

Looks only for positions closer than bound. If successful, modifies pos and bound.

void Page::invalidateBBox ( int  i) const

Invalidate the bounding box at index i (the object is somehow changed).

void Page::insert ( int  i,
TSelect  select,
int  layer,
Object obj 
)

Insert a new object at index i.

Takes ownership of the object.

void Page::append ( TSelect  select,
int  layer,
Object obj 
)

Append a new object.

Takes ownership of the object.

void Page::remove ( int  i)

Remove the object at index i.

void Page::replace ( int  i,
Object obj 
)

Replace the object at index i.

Takes ownership of obj.

bool Page::setAttribute ( int  i,
Property  prop,
Attribute  value,
Attribute  stroke,
Attribute  fill 
)

Set attribute prop of object at index i to value.

This method automatically invalidates the bounding box if a ETextSize property is actually changed.

int Page::primarySelection ( ) const

Return index of primary selection.

Returns -1 if there is no primary selection.

bool Page::hasSelection ( ) const

Returns true iff any object on the page is selected.

void Page::deselectAll ( )

Deselect all objects.

void Page::ensurePrimarySelection ( )

If no object is the primary selection, make the topmost secondary selection the primary one.


The documentation for this class was generated from the following files:
  • ipepage.h
  • ipepage.cpp

ipe-7.1.4/build/doc/classipe_1_1_snap-members.html0000644000175000017500000001760612120621776021636 0ustar otfriedotfried Ipelib: Member List
ipe::Snap Member List

This is the complete list of members for ipe::Snap, including all inherited members.

ESnapAngle enum valueipe::Snap
ESnapAuto enum valueipe::Snap
ESnapBd enum valueipe::Snap
ESnapGrid enum valueipe::Snap
ESnapInt enum valueipe::Snap
ESnapNone enum valueipe::Snap
ESnapVtx enum valueipe::Snap
getLine(const Vector &mouse, const Vector &base) const ipe::Snap
iAngleSizeipe::Snap
iDiripe::Snap
iGridSizeipe::Snap
iGridVisibleipe::Snap
intersectionSnap(Vector &pos, const Page *page, double snapDist) const ipe::Snap
iOriginipe::Snap
iSnapipe::Snap
iSnapDistanceipe::Snap
iWithAxesipe::Snap
setEdge(const Vector &pos, const Page *page)ipe::Snap
simpleSnap(Vector &pos, const Page *page, double snapDist) const ipe::Snap
snap(Vector &pos, const Page *page, double snapDist, Vector *autoOrg=0) const ipe::Snap
snapAngularIntersection(Vector &pos, const Line &l, const Page *page, double snapDist) const ipe::Snap
TSnapModes enum nameipe::Snap

ipe-7.1.4/build/doc/classipe_1_1_a85_stream.html0000644000175000017500000002356512120621776021216 0ustar otfriedotfried Ipelib: ipe::A85Stream Class Reference

#include <ipeutils.h>

Inherits ipe::Stream.

Public Member Functions

 A85Stream (Stream &stream)
virtual void putChar (char ch)
virtual void close ()
- Public Member Functions inherited from ipe::Stream
virtual ~Stream ()
virtual void putString (String s)
virtual void putCString (const char *s)
virtual void putRaw (const char *data, int size)
Streamoperator<< (char ch)
Streamoperator<< (const String &s)
Streamoperator<< (const char *s)
Streamoperator<< (int i)
Streamoperator<< (double d)
void putHexByte (char b)
void putXmlString (String s)

Detailed Description

Filter stream adding ASCII85 encoding.

Constructor & Destructor Documentation

A85Stream::A85Stream ( Stream stream)

Member Function Documentation

void A85Stream::putChar ( char  ch)
virtual

Output character.

Implements ipe::Stream.

void A85Stream::close ( )
virtual

Close the stream. No more writing allowed!

Reimplemented from ipe::Stream.


The documentation for this class was generated from the following files:
  • ipeutils.h
  • ipeutils.cpp

ipe-7.1.4/build/doc/classipe_1_1_painter-members.html0000644000175000017500000005267712120621776022346 0ustar otfriedotfried Ipelib: Member List
ipe::Painter Member List

This is the complete list of members for ipe::Painter, including all inherited members.

addClipPath()ipe::Painter
cascade() const ipe::Painterinline
closePath()ipe::Painter
curveTo(const Vector &v1, const Vector &v2, const Vector &v3)ipe::Painter
curveTo(const Bezier &bezier)ipe::Painterinline
dashStyle() const ipe::Painterinline
dashStyle(std::vector< double > &dashes, double &offset) const ipe::Painter
doAddClipPath()ipe::Painterprotectedvirtual
doClosePath()ipe::Painterprotectedvirtual
doCurveTo(const Vector &v1, const Vector &v2, const Vector &v3)ipe::Painterprotectedvirtual
doDrawArc(const Arc &arc)ipe::Painterprotectedvirtual
doDrawBitmap(Bitmap bitmap)ipe::Painterprotectedvirtual
doDrawPath(TPathMode mode)ipe::Painterprotectedvirtual
doDrawSymbol(Attribute symbol)ipe::Painterprotectedvirtual
doDrawText(const Text *text)ipe::Painterprotectedvirtual
doLineTo(const Vector &v)ipe::Painterprotectedvirtual
doMoveTo(const Vector &v)ipe::Painterprotectedvirtual
doNewPath()ipe::Painterprotectedvirtual
doPop()ipe::Painterprotectedvirtual
doPush()ipe::Painterprotectedvirtual
drawArc(const Arc &arc)ipe::Painter
drawArcAsBezier(double alpha)ipe::Painterprotected
drawBitmap(Bitmap bitmap)ipe::Painter
drawEllipse()ipe::Painter
drawPath(TPathMode mode)ipe::Painter
drawSymbol(Attribute symbol)ipe::Painter
drawText(const Text *text)ipe::Painter
fill() const ipe::Painterinline
fillRule() const ipe::Painterinline
gradient() const ipe::Painterinline
iCascadeipe::Painterprotected
iInPathipe::Painterprotected
iMatrixipe::Painterprotected
iStateipe::Painterprotected
lineCap() const ipe::Painterinline
lineJoin() const ipe::Painterinline
lineTo(const Vector &v)ipe::Painter
matrix() const ipe::Painterinline
moveTo(const Vector &v)ipe::Painter
newPath()ipe::Painter
opacity() const ipe::Painterinline
Painter(const Cascade *style)ipe::Painter
pen() const ipe::Painterinline
pop()ipe::Painter
popMatrix()ipe::Painter
push()ipe::Painter
pushMatrix()ipe::Painter
rect(const Rect &re)ipe::Painter
setDashStyle(Attribute dash)ipe::Painter
setFill(Attribute color)ipe::Painter
setFillRule(TFillRule rule)ipe::Painter
setGradient(Attribute grad)ipe::Painter
setLineCap(TLineCap cap)ipe::Painter
setLineJoin(TLineJoin join)ipe::Painter
setOpacity(Attribute opaq)ipe::Painter
setPen(Attribute pen)ipe::Painter
setStroke(Attribute color)ipe::Painter
setSymFill(Attribute color)ipe::Painter
setSymPen(Attribute wid)ipe::Painter
setSymStroke(Attribute color)ipe::Painter
setTiling(Attribute til)ipe::Painter
stroke() const ipe::Painterinline
symFill() const ipe::Painterinline
symPen() const ipe::Painterinline
symStroke() const ipe::Painterinline
tiling() const ipe::Painterinline
transform(const Matrix &m)ipe::Painter
translate(const Vector &v)ipe::Painter
untransform(TTransformations trans)ipe::Painter
~Painter()ipe::Paintervirtual

ipe-7.1.4/build/doc/classipe_1_1_tool-members.html0000644000175000017500000001014612120621776021642 0ustar otfriedotfried Ipelib: Member List
ipe::Tool Member List

This is the complete list of members for ipe::Tool, including all inherited members.

draw(Painter &painter) const =0ipe::Toolpure virtual
iCanvasipe::Toolprotected
key(int code, int modifiers, String text)ipe::Toolvirtual
mouseButton(int button, bool press)ipe::Toolvirtual
mouseMove()ipe::Toolvirtual
Tool(CanvasBase *canvas)ipe::Toolprotected
~Tool()ipe::Toolvirtual

ipe-7.1.4/build/doc/manual.html0000644000175000017500000000554112120621776016172 0ustar otfriedotfried Ipe Manual ipe-7.1.4/build/doc/manual_54.html0000644000175000017500000000617212120621776016503 0ustar otfriedotfried Ipe Manual -- Footnotes
TopContentsFootnotes

Footnotes

 (1)
The line width can be set to zero to get the thinnest line the device can produce (i.e. approximately the same as 0.15 for a 600 dpi printer or 0.3 for a 300 dpi printer). The PDF and Postscript authorities discourage using this feature, since it makes your Postscript files device-dependent.
 (2)
J. D. Foley, A. Van Dam, S. K. Feiner, and J. F. Hughes, Computer Graphics: Principles and Practice, Addison-Wesley, 1990.
 (3)
Fifi is called after the dog in the rogue computer game installed on most Unix systems in the 1980's, because it also keeps running around your feet.
 (4)
In fact, in modern LaTeX installations, epsfig.sty is just a small wrapper around graphics.sty.
ipe-7.1.4/build/doc/manual_11.html0000644000175000017500000000707712120621776016501 0ustar otfriedotfried Ipe Manual -- 3.8 Zoom and pan
3.9 Groups3 General Concepts3.7 Symbolic and absolute attributes3.8 Zoom and pan

3.8 Zoom and pan

You can zoom in and out the current drawing using a mouse wheel or the zoom functions. The minimum and maximum resolution can be customized. Ipe displays the current resolution at the bottom right (behind the mouse coordinates).

Related are the functions Normal size (which sets the resolution to 72 pixels per inch), Fit page (which chooses the resolution so that the current page fills the canvas), Fit objects (which chooses the resolution such that the objects on the page fill the screen), and Fit selection (which does the same for the selected objects only). All of these are in the Zoom menu.

You can pan the drawing either with the mouse in Pan mode, or by pressing the "x" key ("here") with the mouse anywhere on the canvas. The drawing is then panned such that the cursor position is moved to the center of the canvas. This shortcut has the advantage that it also works while you are in the middle of any drawing operation. Since the same holds for the zoom in and zoom out buttons and keys, you can home in on any feature of your drawing while you are adding or editing another object.

ipe-7.1.4/build/doc/classipe_1_1_segment.html0000644000175000017500000003630412120621776020703 0ustar otfriedotfried Ipelib: ipe::Segment Class Reference

#include <ipegeo.h>

Public Member Functions

 Segment ()
 Segment (const Vector &p, const Vector &q)
Line line () const
double distance (const Vector &v, double bound) const
double distance (const Vector &v) const
bool project (const Vector &v, Vector &projection) const
bool intersects (const Segment &seg, Vector &pt) const
bool intersects (const Line &l, Vector &pt) const
bool snap (const Vector &mouse, Vector &pos, double &bound) const

Public Attributes

Vector iP
Vector iQ

Detailed Description

A directed line segment.

Constructor & Destructor Documentation

ipe::Segment::Segment ( )
inline

Create uninitialized segment.

ipe::Segment::Segment ( const Vector p,
const Vector q 
)
inlineexplicit

Member Function Documentation

Line ipe::Segment::line ( ) const
inline

Return directed line supporting the segment.

double Segment::distance ( const Vector v,
double  bound 
) const

Returns distance between segment and point v, but may just return bound when its larger than bound.

double Segment::distance ( const Vector v) const

Returns distance between segment and point v

bool Segment::project ( const Vector v,
Vector projection 
) const

Project point v orthogonally on segment. Returns false if the point falls outside the segment.

bool Segment::intersects ( const Segment seg,
Vector pt 
) const

Compute intersection point. Return false if segs don't intersect.

bool Segment::intersects ( const Line l,
Vector pt 
) const

Compute intersection point. Return false if no intersection.

bool Segment::snap ( const Vector mouse,
Vector pos,
double &  bound 
) const

Snap mouse position to this segment.

If distance between mouse and the segment is less than bound, then set pos to the point on the segment, bound to the distance, and return true.

Member Data Documentation

Vector ipe::Segment::iP

First endpoint.

Vector ipe::Segment::iQ

Second endpoint.


The documentation for this class was generated from the following files:
  • ipegeo.h
  • ipegeo.cpp

ipe-7.1.4/build/doc/classipe_1_1_latex.html0000644000175000017500000002755312120621776020364 0ustar otfriedotfried Ipelib: ipe::Latex Class Reference
ipe::Latex Class Reference

#include <ipelatex.h>

Classes

struct  SText

Public Member Functions

 Latex (const Cascade *sheet)
 ~Latex ()
int scanObject (const Object *obj)
int scanPage (Page *page)
int createLatexSource (Stream &stream, String preamble)
bool readPdf (DataSource &source)
bool updateTextObjects ()
FontPool * takeFontPool ()

Friends

class ipe::TextCollectingVisitor

Detailed Description

Object that converts latex source to PDF format.

This object is responsible for creating the PDF representation of text objects.

Constructor & Destructor Documentation

Latex::Latex ( const Cascade sheet)

Create a converter object.

Latex::~Latex ( )

Destructor.

Member Function Documentation

int Latex::scanObject ( const Object obj)

Scan an object and insert all text objects into Latex's list. Returns total number of text objects found so far.

int Latex::scanPage ( Page page)

Scan a page and insert all text objects into Latex's list. Returns total number of text objects found so far.

int Latex::createLatexSource ( Stream stream,
String  preamble 
)

Create a Latex source file with all the text objects collected before. The client should have prepared a directory for the Pdflatex run, and pass the name of the Latex source file to be written by Latex.

Returns the number of text objects that did not yet have an XForm, or a negative error code.

bool Latex::readPdf ( DataSource source)

Read the PDF file created by Pdflatex.

Must have performed the call to Pdflatex, and pass the name of the resulting output file.

bool Latex::updateTextObjects ( )

Notify all text objects about their updated PDF code.

Returns true if successful.

FontPool * Latex::takeFontPool ( )

Return the newly created font pool and pass ownership of pool to caller.

Friends And Related Function Documentation

friend class ipe::TextCollectingVisitor
friend

The documentation for this class was generated from the following files:
  • ipelatex.h
  • ipelatex.cpp

ipe-7.1.4/build/doc/open.png0000644000175000017500000000017312120621776015472 0ustar otfriedotfried‰PNG  IHDR à‘BIDATxíÝÁ €0 Ð׬ՙ\Àº€39—b!©9{|ðI>$#Àß´ý8/¨ÄØzƒ/Ï>2À[ÎgiU,/¬~¼Ï\ Ä9Ù¸IEND®B`‚ipe-7.1.4/build/doc/classipe_1_1_string-members.html0000644000175000017500000002277412120621776022205 0ustar otfriedotfried Ipelib: Member List
ipe::String Member List

This is the complete list of members for ipe::String, including all inherited members.

append(const String &rhs)ipe::String
append(char ch)ipe::String
data() const ipe::Stringinline
empty() const ipe::Stringinline
erase()ipe::String
find(char ch) const ipe::String
find(const char *rhs) const ipe::String
isEmpty() const ipe::Stringinline
left(int i) const ipe::Stringinline
operator!=(const String &rhs) const ipe::Stringinline
operator+(const String &rhs) const ipe::String
operator+=(const String &rhs)ipe::Stringinline
operator+=(char ch)ipe::Stringinline
operator<(const String &rhs) const ipe::String
operator=(const String &rhs)ipe::String
operator==(const String &rhs) const ipe::String
operator[](int i) const ipe::Stringinline
rfind(char ch) const ipe::String
right(int i) const ipe::String
size() const ipe::Stringinline
String()ipe::String
String(const char *str)ipe::String
String(const String &rhs)ipe::String
String(const String &rhs, int index, int len)ipe::String
substr(int i, int len=-1) const ipe::Stringinline
unicode(int &index) const ipe::String
z() const ipe::String
~String()ipe::String

ipe-7.1.4/build/doc/namespacemembers_vars.html0000644000175000017500000000515412120621776021257 0ustar otfriedotfried Ipelib: Namespace Members
 
  • FILE_FORMAT : ipe
  • IPELIB_VERSION : ipe
  • kind_names : ipe
  • OLDEST_FILE_FORMAT : ipe
  • property_names : ipe

ipe-7.1.4/build/doc/annotated.html0000644000175000017500000012451512120621776016675 0ustar otfriedotfried Ipelib: Class List
Class List
Here are the classes, structs, unions and interfaces with brief descriptions:
[detail level 123]
oNipe
|oCColorAn absolute RGB color
|oCTilingA tiling pattern
|oCGradientA gradient pattern
|oCLayoutLayout of a Page
|oCTextPaddingPadding for text bounding box
|oCEffectEffect that Acrobat Reader will show on page change
|oCRepositoryRepository of strings
|oCAttributeAn attribute of an Ipe Object
|oCAllAttributesCollection of all object attributes
|oCStringStrings and buffers
|oCFixedFixed point number with three (decimal) fractional digits
|oCLexLexical analyser. Seeded with a string
|oCBufferA memory buffer
|oCStreamAbstract base class for output streams
|oCTellStreamAdds position feedback to IpeStream
|oCStringStreamStream writing into an String
|oCFileStreamStream writing into an open file
|oCDataSourceInterface for getting data for parsing
|oCFileSourceData source for parsing from a file
|oCBufferSourceData source for parsing from a buffer
|oCPlatformPlatform dependent methods
|oCBitmapA bitmap
|oCDocumentThe model for an Ipe document
|oCObjectFactoryFactory for Ipe leaf objects
|oCFontA text font
|oCAngleA double that's an angle
|oCVectorTwo-dimensional vector
|oCRectAxis-parallel rectangle (which can be empty)
|oCLineA directed line
|oCSegmentA directed line segment
|oCBezierA cubic Bezier spline
|oCLinearLinear transformation in the plane (2x2 matrix)
|oCMatrixHomogeneous transformation in the plane
|oCArcAn arc of an ellipse
|oCGroupThe group object
|oCImageThe image object
|oCImlParserXML Parser for Ipe documents and style sheets
|oCLatexObject that converts latex source to PDF format
|oCIpeletHelperService provider for Ipelets
|oCIpeletDataInformation provided to an ipelet when it is run
|oCIpeletAbstract base class for Ipelets
|oCObjectBase class for all Ipe objects, composite or leaf
|oCVisitorBase class for visitors to Object
|oCPageAn Ipe document page
|oCPainterInterface for drawing
|oCPathThe path object (polylines, polygons, and generalizations)
|oCPdfObjAbstract base class for PDF objects
|oCPdfNullThe PDF null object
|oCPdfBoolThe PDF bool object
|oCPdfNumberThe PDF number object
|oCPdfStringThe PDF string object
|oCPdfNameThe PDF name object
|oCPdfRefThe PDF reference object (indirect object)
|oCPdfArrayThe PDF array object
|oCPdfDictThe PDF dictionary and stream objects
|oCPdfTokenA PDF lexical token
|oCPdfParserPDF parser
|oCPdfFileAll information obtained by parsing a PDF file
|oCPdfPainter
|oCPdfWriterCreate PDF file
|oCPsPainter
|oCPsWriterCreate Postscript file
|oCReferenceThe reference object
|oCCurveSegmentA segment on an SubPath
|oCSubPathA subpath of a Path
|oCEllipseAn ellipse subpath
|oCClosedSplineA closed B-spline curve
|oCCurveSubpath consisting of a sequence of CurveSegment's
|oCShapeA geometric shape, consisting of several (open or closed) subpaths
|oCSnapPerforms snapping operations, and stores snapping state
|oCSymbolA symbol is a named object defined in an ipe::StyleSheet
|oCStyleSheetA style sheet maps symbolic names to absolute values
|oCCascadeA cascade of style sheets
|oCTextThe text object
|oCBitmapFinderA visitor that recursively scans objects and collects all bitmaps
|oCBBoxPainterPaint objects using this painter to compute an accurate bounding box
|oCA85StreamFilter stream adding ASCII85 encoding
|oCBase64StreamFilter stream adding Base64 encoding
|oCDeflateStreamFilter stream adding flate compression
|oCA85SourceFilter source adding ASCII85 decoding
|oCBase64SourceFilter source adding Base64 decoding
|oCInflateSourceFilter source adding flate decompression
|oCXmlAttributesStores attributes of an XML tag
|oCXmlParserBase class for XML stream parsing
|oCCairoPainterIpe Painter using Cairo and Freetype as a backend
|oCFaceA typeface (aka font), actually loaded (from a font file or PDF file)
|oCFontsProvides the fonts used to render text
|oCThumbnail
|oCCanvasObserver
|oCCanvasBase
|oCCanvasA widget (control) that displays an Ipe document page
|oCPageSelector
|oCToolAbstract base class for various canvas tools
|oCPanToolA tool for panning the canvas
|oCSelectToolA tool for selecting objects
|\CTransformToolA tool for transforming the selected objects on the canvas
oNipeqt
\CIpeAutoPtr

ipe-7.1.4/build/doc/ftv2mnode.png0000644000175000017500000000036612120621776016441 0ustar otfriedotfried‰PNG  IHDRɪ|½IDATxíÝ!NAÅñ¤‡à\ ÷à Um@`Ô5iÒ`ëh ‚ÅW7] b§ÝˆŠ&oföÍd¾YÔ4 üšcø ‡€´‹Åòù3v=¼]†§µ\B… I¿‹=B·™B¡®;¸k´µ W°ÍN@vyÍÑÖ4ãß÷]ÈâYìã§|M}]ÔÚx6a }ôdׇØYüú¨>¤||5?Ó>|žB"¡î'¡IEND®B`‚ipe-7.1.4/build/doc/group__geo.html0000644000175000017500000002746112120621776017047 0ustar otfriedotfried Ipelib: Ipe Geometry
Ipe Geometry

Classes

class  ipe::Angle
 A double that's an angle. More...
class  ipe::Vector
 Two-dimensional vector. More...
class  ipe::Rect
 Axis-parallel rectangle (which can be empty) More...
class  ipe::Line
 A directed line. More...
class  ipe::Segment
 A directed line segment. More...
class  ipe::Linear
 Linear transformation in the plane (2x2 matrix). More...
class  ipe::Matrix
 Homogeneous transformation in the plane. More...
class  ipe::Bezier
 A cubic Bezier spline. More...
class  ipe::Arc
 An arc of an ellipse. More...
class  ipe::CurveSegment
 A segment on an SubPath. More...
class  ipe::Curve
 Subpath consisting of a sequence of CurveSegment's. More...
class  ipe::SubPath
 A subpath of a Path. More...
class  ipe::Ellipse
 An ellipse subpath. More...
class  ipe::ClosedSpline
 A closed B-spline curve. More...
class  ipe::Shape
 A geometric shape, consisting of several (open or closed) subpaths. More...

Functions

template<class T >
ipe::max (const T &lhs, const T &rhs)
template<class T >
ipe::min (const T &lhs, const T &rhs)
double ipe::abs (double val)

Detailed Description

Geometric primitives for Ipe.

The IpeGeo module provides a few classes for constant-size geometric primitives, such as vector, axis-aligned rectangles, lines, rays, line segments, etc.

Function Documentation

template<class T >
T ipe::max ( const T &  lhs,
const T &  rhs 
)
inline

Maximum of two values.

template<class T >
T ipe::min ( const T &  lhs,
const T &  rhs 
)
inline

Minimum of two values.

double ipe::abs ( double  val)
inline

Absolute value.


ipe-7.1.4/build/doc/functions_0x67.html0000644000175000017500000001777412120621776017524 0ustar otfriedotfried Ipelib: Class Members
Here is a list of all class members with links to the classes they belong to:

- g -


ipe-7.1.4/build/doc/manual_26.html0000644000175000017500000001675112120621776016506 0ustar otfriedotfried Ipe Manual -- 5.5 Examples
5 Snapping5.4 Interaction of the snapping modes5.5 Examples

5.5 Examples

It takes some time and practice to feel fully at ease with the different snapping modes, especially angular snapping. Here are some examples showing what can be done with angular snapping.

Example 1:

We are given segments s1, s2, and e, and we want to add the dashed vertical extensions through p and q.

  • set F4 and F5 snapping on, go into line mode, and reset axis system with Shift-F2,
  • go near p, press F1 and F8 to set origin and to turn on angular snap.
  • go near p', click left, and extend segment to s2.
  • go near q, press F1 to reset origin, and draw second extension in the same way.

Example 2:

We are given the polygon C, and we want to draw the bracket b, indicating its vertical extension.

  • set F4 and F9 snapping on, go into line mode, reset axis system, set snap angle to 90 degrees.
  • go near p, press F1 and F8 to set origin and angular snapping
  • go to x, click left, extend segment to y, click left
  • now we want to have z on a horizontal line through q: go near q, and press F1 and F8 to reset origin and to turn on angular snapping. Now both angular snapping modes are on, the snap lines intersect in z.
  • click left at z, goto x and press F1, goto t and finish bracket.

Example 3:

We want to draw the following "skyline". The only problem is to get q horizontally aligned with p.

  • draw the baseline using automatic angular snapping to get it horizontal.
  • place p with boundary snapping, draw the rectilinear curve up to r with automatic angular snapping in 90 degrees mode.
  • now go to p and press F1 and F8. The snap lines intersect in q. Click there, turn off angular snapping with Shift-F2, and finish curve. The last point is placed with boundary snapping.

Example 4:

We want to draw a line through p, tangent to C in q.

  • with vertex snapping on, put origin at p with F1
  • go to q and press F2. This puts the base direction from p to q.
  • set angular snapping with F8 and draw line.

Example 5:

We want to draw the following "windmill". The angle of the sector and between sectors should be 30 degrees.

  • set vertex snapping, snap angle to 30 degrees, reset axis system with Shift-F1,
  • with automatic angular snapping, draw a horizontal segment pq.
  • go to p, place origin and turn on angular snapping with F1 and F8,
  • duplicate segment with d, go to q and pick up q for rotation (with Ctrl and the middle mouse button). Rotate until segment falls on the next snap line.
  • turn off angular snapping with F8. Choose arc mode, variant "center & two points".
  • go to p, click for center. Go to q, click for first endpoint of arc, and at r for the second endpoint. Select all, and group.
  • turn angular snapping on again. Duplicate sector, and rotate by 60 degrees using angular snapping.
  • duplicate and rotate four more times.

Example 6:

We want to draw a c-oriented polygon, where the angles between successive segments are multiples of 30 degrees. The automatic angular snapping mode makes this pretty easy, but there is a little catch: How do we place the ultimate vertex such that it is at the same time properly aligned to the penultimate and to the very first vertex?

  • set snap angle to 30 degrees, and turn on automatic angular snapping.
  • click first vertex p and draw the polygon up to the penultimate vertex q.
  • it remains to place r such that it is in a legal position both with respect to q and p. The automatic angular snapping mode ensures the position with respect to q. We will use angular snapping from p to get it right: Go near p and turn on vertex snapping. Press F1 to place the origin at p and F8 to turn on angular snapping. Now it is trivial to place r.
ipe-7.1.4/build/doc/namespacemembers_enum.html0000644000175000017500000000632012120621776021244 0ustar otfriedotfried Ipelib: Namespace Members
 
  • Kind : ipe
  • Property : ipe
  • TFillRule : ipe
  • THorizontalAlignment : ipe
  • TLineCap : ipe
  • TLineJoin : ipe
  • TPathMode : ipe
  • TPinned : ipe
  • TSelect : ipe
  • TTransformations : ipe
  • TVerticalAlignment : ipe

ipe-7.1.4/build/doc/structipe_1_1_layout.html0000644000175000017500000002173112120621776020773 0ustar otfriedotfried Ipelib: ipe::Layout Struct Reference

#include <ipeattributes.h>

Public Member Functions

 Layout ()
bool isNull () const
Rect paper () const

Public Attributes

Vector iPaperSize
Vector iOrigin
Vector iFrameSize
double iParagraphSkip
bool iCrop

Detailed Description

Layout of a Page.

Constructor & Destructor Documentation

ipe::Layout::Layout ( )
inline

Create null layout.

Member Function Documentation

bool ipe::Layout::isNull ( ) const
inline

Is this an undefined (null) layout?

Rect ipe::Layout::paper ( ) const
inline

Return rectangle describing the paper.

Member Data Documentation

Vector ipe::Layout::iPaperSize

Dimensions of the media.

Vector ipe::Layout::iOrigin

Origin of the Ipe coordinate system relative to the paper.

Vector ipe::Layout::iFrameSize

Size of the frame (the drawing area).

double ipe::Layout::iParagraphSkip

Paragraph skip (between textboxes).

bool ipe::Layout::iCrop

Crop paper to drawing.


The documentation for this struct was generated from the following file:
  • ipeattributes.h

ipe-7.1.4/build/doc/functions_0x74.html0000644000175000017500000003004412120621776017503 0ustar otfriedotfried Ipelib: Class Members
Here is a list of all class members with links to the classes they belong to:

- t -


ipe-7.1.4/build/doc/classipe_1_1_pdf_null.html0000644000175000017500000002276212120621776021047 0ustar otfriedotfried Ipelib: ipe::PdfNull Class Reference
ipe::PdfNull Class Reference

#include <ipepdfparser.h>

Inherits ipe::PdfObj.

Public Member Functions

 PdfNull ()
virtual const PdfNullnull () const
virtual void write (Stream &stream) const
- Public Member Functions inherited from ipe::PdfObj
virtual ~PdfObj ()=0
virtual const PdfBoolboolean () const
virtual const PdfNumbernumber () const
virtual const PdfStringstring () const
virtual const PdfNamename () const
virtual const PdfRefref () const
virtual const PdfArrayarray () const
virtual const PdfDictdict () const
String repr () const

Detailed Description

The PDF null object.

Constructor & Destructor Documentation

ipe::PdfNull::PdfNull ( )
inlineexplicit

Member Function Documentation

const PdfNull * PdfNull::null ( ) const
virtual

Return this object as PDF null object.

Reimplemented from ipe::PdfObj.

void PdfNull::write ( Stream stream) const
virtual

Implements ipe::PdfObj.


The documentation for this class was generated from the following files:
  • ipepdfparser.h
  • ipepdfparser.cpp

ipe-7.1.4/build/doc/nav_h.png0000644000175000017500000000014212120621776015620 0ustar otfriedotfried‰PNG  IHDR ,é@)IDATxíÝA @BQ­³šÛ›Ð¢Žáà) )ëý éaÅèÜ¿Æo‡RlÐßIEND®B`‚ipe-7.1.4/build/doc/lua-ipelets.html0000644000175000017500000001125612120621776017141 0ustar otfriedotfried Ipelib: Ipelets written in Lua
Ipelets written in Lua

Ipelets written in Lua have access to the entire Ipe user interface, and can in principle do anything that Ipe can do.

An ipelet is a Lua script that is placed in Ipe's ipelet directory.

The script needs to define three global variables, namely label, about, and either run or methods (or both).

  • label is a string containing the label (that is, the name) of the ipelet. It is shown in the Ipelet menu.
  • about is a string containing an 'about' or copyright notice for the ipelet. Ipe displays this in the "About the ipelets" box.
  • run is used if the ipelet contains only a single method. When the ipelet is invoked, the function run is called by Lua.
  • methods is used if the ipelet contains more than one method. It is an array with an entry for each method. Each entry is a table with keys label (defining the label of the method) and run (a Lua function that will be called by Ipe to execute this method). If an entry does not have a run field, then the global run method is called instead.

If an ipelet defines no label variable, then the ipelet is not added to the Ipelet menu. Such ipelets can be used to customize Ipe.

When Ipe invokes an ipelet, the Lua method is called with two arguments: the first argument model is the active Ipe user interface, the second is the index of the method being invoked.

The "global" environment of the ipelet is a private environment for this ipelet only, so there is no need to fear polluting the global namespace - you can use names here freely. The commonly used names have been imported from Ipe's global namespace already, and you can access any others you may need through _G.

It is important that the ipelet does not directly modify the document. This would mess up the undo stack, and could cause Ipe to crash on undo or redo. Instead, to modify the document the ipelet needs to create an undo item t and call model:register(t).

If all the ipelet does is to create a new object obj, then it can simply call

model:creation("create new object", obj)

The following are some useful methods and data structures:

model.doc     -- the document
model.pno     -- current page number
model.vno     -- current view number

model:page()  -- returns current page

model:register(t) -- register undo item and execute its redo method
model:creation("label", obj)  -- register undo item for object creation

model:warning(text, details)  -- display a warning box

model.attributes   -- attributes currently set in user interface
model.snap         -- currently active snap settings

Look at the existing ipelets for inspiration.


ipe-7.1.4/build/doc/classipe_1_1_pdf_name-members.html0000644000175000017500000001347212120621776022443 0ustar otfriedotfried Ipelib: Member List
ipe::PdfName Member List

This is the complete list of members for ipe::PdfName, including all inherited members.

array() const ipe::PdfObjvirtual
boolean() const ipe::PdfObjvirtual
dict() const ipe::PdfObjvirtual
name() const ipe::PdfNamevirtual
null() const ipe::PdfObjvirtual
number() const ipe::PdfObjvirtual
PdfName(const String &val)ipe::PdfNameinlineexplicit
ref() const ipe::PdfObjvirtual
repr() const ipe::PdfObj
string() const ipe::PdfObjvirtual
value() const ipe::PdfNameinline
write(Stream &stream) const ipe::PdfNamevirtual
~PdfObj()=0ipe::PdfObjpure virtual

ipe-7.1.4/build/doc/classipe_1_1_visitor.html0000644000175000017500000002372112120621776020737 0ustar otfriedotfried Ipelib: ipe::Visitor Class Reference

#include <ipeobject.h>

Inherited by CollectSegs, ipe::BitmapFinder, ipe::TextCollectingVisitor, and TextBoxVisitor.

Public Member Functions

virtual ~Visitor ()
virtual void visitGroup (const Group *obj)
virtual void visitPath (const Path *obj)
virtual void visitText (const Text *obj)
virtual void visitImage (const Image *obj)
virtual void visitReference (const Reference *obj)

Detailed Description

Base class for visitors to Object.

Many operations on Ipe Objects are implemented as visitors, all derived from Visitor.

The default implementation of each visitXXX member does nothing.

Constructor & Destructor Documentation

Visitor::~Visitor ( )
virtual

Pure virtual destructor.

Member Function Documentation

void Visitor::visitGroup ( const Group obj)
virtual

Called on an Group object.

Reimplemented in ipe::BitmapFinder.

void Visitor::visitPath ( const Path obj)
virtual

Called on an Path object.

void Visitor::visitText ( const Text obj)
virtual

Called on an Text object.

void Visitor::visitImage ( const Image obj)
virtual

Called on an Image object.

Reimplemented in ipe::BitmapFinder.

void Visitor::visitReference ( const Reference obj)
virtual

Called on an Reference object.


The documentation for this class was generated from the following files:
  • ipeobject.h
  • ipeobject.cpp

ipe-7.1.4/build/doc/classipe_1_1_angle.html0000644000175000017500000002402512120621776020324 0ustar otfriedotfried Ipelib: ipe::Angle Class Reference

#include <ipegeo.h>

Public Member Functions

 Angle ()
 Angle (double alpha)
 operator double () const
double degrees () const
Angle normalize (double lowlimit)
bool liesBetween (Angle small, Angle large) const

Static Public Member Functions

static Angle Degrees (double alpha)

Detailed Description

A double that's an angle.

An Angle is really nothing more than a double. Having a separate type is sometimes useful, for instance in the Vector constructor, and this class serves as the right place for a few utility functions. It also makes it clear whether a value is in radians or in degrees.

Constructor & Destructor Documentation

ipe::Angle::Angle ( )
inlineexplicit

Construct uninitialized angle.

ipe::Angle::Angle ( double  alpha)
inline

Construct an angle (in radians).

Member Function Documentation

static Angle ipe::Angle::Degrees ( double  alpha)
inlinestatic

Construct an angle in degrees.

ipe::Angle::operator double ( ) const
inline

Return value (in radians).

double Angle::degrees ( ) const
Angle Angle::normalize ( double  lowlimit)

Normalize the value to the range lowlimit .. lowlimit + 2 pi.

This Angle object is modified, a copy is returned.

bool Angle::liesBetween ( Angle  small,
Angle  large 
) const

When considering the positively oriented circle arc from angle small to large, does it cover this angle?


The documentation for this class was generated from the following files:
  • ipegeo.h
  • ipegeo.cpp

ipe-7.1.4/build/doc/classipe_1_1_closed_spline-members.html0000644000175000017500000001765612120621776023525 0ustar otfriedotfried Ipelib: Member List
ipe::ClosedSpline Member List

This is the complete list of members for ipe::ClosedSpline, including all inherited members.

addToBBox(Rect &box, const Matrix &m, bool cp) const ipe::ClosedSplinevirtual
asClosedSpline() const ipe::ClosedSplinevirtual
asCurve() const ipe::SubPathvirtual
asEllipse() const ipe::SubPathvirtual
beziers(std::vector< Bezier > &bez) const ipe::ClosedSpline
closed() const ipe::SubPathvirtual
ClosedSpline(const std::vector< Vector > &v)ipe::ClosedSpline
distance(const Vector &v, const Matrix &m, double bound) const ipe::ClosedSplinevirtual
draw(Painter &painter) const ipe::ClosedSplinevirtual
EClosedSpline enum valueipe::SubPath
ECurve enum valueipe::SubPath
EEllipse enum valueipe::SubPath
iCPipe::ClosedSpline
save(Stream &stream) const ipe::ClosedSplinevirtual
snapBnd(const Vector &mouse, const Matrix &m, Vector &pos, double &bound) const ipe::ClosedSplinevirtual
snapVtx(const Vector &mouse, const Matrix &m, Vector &pos, double &bound) const ipe::ClosedSplinevirtual
type() const ipe::ClosedSplinevirtual
Type enum nameipe::SubPath
~SubPath()=0ipe::SubPathpure virtual

ipe-7.1.4/build/doc/namespacemembers_type.html0000644000175000017500000000427512120621776021270 0ustar otfriedotfried Ipelib: Namespace Members
 
  • AttributeSeq : ipe

ipe-7.1.4/build/doc/classipe_1_1_xml_attributes.html0000644000175000017500000003242712120621776022311 0ustar otfriedotfried Ipelib: ipe::XmlAttributes Class Reference
ipe::XmlAttributes Class Reference

#include <ipexml.h>

Public Types

typedef Map::const_iterator const_iterator

Public Member Functions

const_iterator begin () const
const_iterator end () const
 XmlAttributes ()
void clear ()
String operator[] (String str) const
bool has (String str) const
bool has (String str, String &val) const
void add (String key, String val)
void setSlash ()
bool slash () const

Detailed Description

Stores attributes of an XML tag.

Member Typedef Documentation

typedef Map::const_iterator ipe::XmlAttributes::const_iterator

Iterator for (key, value) pairs.

Constructor & Destructor Documentation

XmlAttributes::XmlAttributes ( )

Constructor for an empty collection.

Member Function Documentation

const_iterator ipe::XmlAttributes::begin ( ) const
inline

Return const iterator for first attribute.

const_iterator ipe::XmlAttributes::end ( ) const
inline

Return const iterator for end of attributes.

void XmlAttributes::clear ( )

Remove all attributes.

String XmlAttributes::operator[] ( String  str) const

Return attribute with given key.

Returns an empty string if no attribute with this key exists.

bool XmlAttributes::has ( String  str) const

Check whether attribute exists.

bool XmlAttributes::has ( String  str,
String val 
) const

Check whether attribute exists, set val if so.

void XmlAttributes::add ( String  key,
String  val 
)

Add a new attribute.

void ipe::XmlAttributes::setSlash ( )
inline

Set that the tag contains the final /.

bool ipe::XmlAttributes::slash ( ) const
inline

Return whether tag contains the final /.


The documentation for this class was generated from the following files:
  • ipexml.h
  • ipexml.cpp

ipe-7.1.4/build/doc/classipe_1_1_page_selector-members.html0000644000175000017500000000677212120621776023513 0ustar otfriedotfried Ipelib: Member List
ipe::PageSelector Member List

This is the complete list of members for ipe::PageSelector, including all inherited members.

PageSelector(Document *doc, int page, int startIndex, int width, QWidget *parent=0)ipe::PageSelector
selectedIndex() const ipe::PageSelectorinline
selectionMade()ipe::PageSelectorsignal
selectPageOrView(Document *doc, int page=-1, int startIndex=0, int pageWidth=240, int width=600, int height=480)ipe::PageSelectorstatic

ipe-7.1.4/build/doc/bdwn.png0000644000175000017500000000022312120621776015457 0ustar otfriedotfried‰PNG  IHDR5åZIDATxíË € DŸP–1ñlžmÀ r±j².e è†D[ØÉ¾ÙÏÔ¼µ¦ã´Þ|陣6€Všë3´Å?Ls'(}¬>+ žKó÷¥¿ch`‚ ^׃ÞnIEND®B`‚ipe-7.1.4/build/doc/structipe_1_1_tiling.html0000644000175000017500000001057712120621776020752 0ustar otfriedotfried Ipelib: ipe::Tiling Struct Reference
ipe::Tiling Struct Reference

#include <ipeattributes.h>

Public Attributes

Angle iAngle
double iStep
double iWidth

Detailed Description

A tiling pattern.

Member Data Documentation

Angle ipe::Tiling::iAngle
double ipe::Tiling::iStep
double ipe::Tiling::iWidth

The documentation for this struct was generated from the following file:
  • ipeattributes.h

ipe-7.1.4/build/doc/classipe_1_1_platform.html0000644000175000017500000003447612120621776021075 0ustar otfriedotfried Ipelib: ipe::Platform Class Reference

#include <ipebase.h>

Public Types

typedef void(* DebugHandler )(const char *)

Static Public Member Functions

static int libVersion ()
static void initLib (int version)
static void setDebug (bool debug)
static char pathSeparator ()
static String currentDirectory ()
static String latexDirectory ()
static String fontmapFile ()
static bool fileExists (String fname)
static String readFile (String fname)
static int runPdfLatex (String dir)

Detailed Description

Platform dependent methods.

Member Typedef Documentation

typedef void(* ipe::Platform::DebugHandler)(const char *)

Member Function Documentation

int Platform::libVersion ( )
static

Return the Ipelib version.

This is available as a function so that one can verify what version of Ipelib one has actually linked with (as opposed to the header files used during compilation).

void Platform::initLib ( int  version)
static

Initialize Ipelib.

This method must be called before Ipelib is used.

It sets the LC_NUMERIC locale to 'C', which is necessary for correct loading and saving of Ipe objects. The method also checks that the correct version of Ipelib is loaded, and aborts with an error message if the version is not correct. Also enables ipeDebug messages if environment variable IPEDEBUG is defined. (You can override this using setDebug).

void Platform::setDebug ( bool  debug)
static

Enable or disable display of ipeDebug messages.

char Platform::pathSeparator ( )
static

Return correct path separator for this platform.

String Platform::currentDirectory ( )
static

Returns current working directory.

Returns empty string if something fails.

String Platform::latexDirectory ( )
static

Returns directory for running Latex.

The directory is created if it does not exist. Returns an empty string if the directory cannot be found or cannot be created. The directory returned ends in the path separator.

String Platform::fontmapFile ( )
static

Returns filename of fontmap.

bool Platform::fileExists ( String  fname)
static

Determine whether file exists.

String Platform::readFile ( String  fname)
static

Read entire file into string.

Returns an empty string if file cannot be found or read. There is no way to distinguish an empty file from this.

int Platform::runPdfLatex ( String  dir)
static

Runs pdflatex on file text.tex in given directory.


The documentation for this class was generated from the following files:
  • ipebase.h
  • ipeplatform.cpp

ipe-7.1.4/build/doc/classipe_1_1_object_factory-members.html0000644000175000017500000000561512120621776023667 0ustar otfriedotfried Ipelib: Member List
ipe::ObjectFactory Member List

This is the complete list of members for ipe::ObjectFactory, including all inherited members.

createImage(String name, const XmlAttributes &attr, Bitmap bitmap)ipe::ObjectFactorystatic
createObject(String name, const XmlAttributes &attr, String data)ipe::ObjectFactorystatic

ipe-7.1.4/build/doc/structipe_1_1_effect.html0000644000175000017500000003104312120621776020707 0ustar otfriedotfried Ipelib: ipe::Effect Class Reference

#include <ipeattributes.h>

Public Types

enum  TEffect {
  ENormal, ESplitHI, ESplitHO, ESplitVI,
  ESplitVO, EBlindsH, EBlindsV, EBoxI,
  EBoxO, EWipeLR, EWipeBT, EWipeRL,
  EWipeTB, EDissolve, EGlitterLR, EGlitterTB,
  EGlitterD
}

Public Member Functions

 Effect ()
void pageDictionary (Stream &stream) const

Public Attributes

TEffect iEffect
int iTransitionTime
int iDuration

Detailed Description

Effect that Acrobat Reader will show on page change.

Acrobat Reader and other PDF viewers can show a special effect when a new page of the document is shown. This class describes such an effect.

Member Enumeration Documentation

The various fancy effects that Acrobat Reader will show.

Enumerator:
ENormal 
ESplitHI 
ESplitHO 
ESplitVI 
ESplitVO 
EBlindsH 
EBlindsV 
EBoxI 
EBoxO 
EWipeLR 
EWipeBT 
EWipeRL 
EWipeTB 
EDissolve 
EGlitterLR 
EGlitterTB 
EGlitterD 

Constructor & Destructor Documentation

Effect::Effect ( )

Construct default effect.

Member Function Documentation

void Effect::pageDictionary ( Stream stream) const

Write part of page dictionary.

Write part of page dictionary indicating effect, including the two keys /Dur and /Trans.

Member Data Documentation

TEffect ipe::Effect::iEffect
int ipe::Effect::iTransitionTime
int ipe::Effect::iDuration

The documentation for this class was generated from the following files:
  • ipeattributes.h
  • ipeattributes.cpp

ipe-7.1.4/build/doc/classipe_1_1_deflate_stream.html0000644000175000017500000003212012120621776022210 0ustar otfriedotfried Ipelib: ipe::DeflateStream Class Reference

#include <ipeutils.h>

Inherits ipe::Stream.

Public Member Functions

 DeflateStream (Stream &stream, int level)
virtual ~DeflateStream ()
virtual void putChar (char ch)
virtual void close ()
- Public Member Functions inherited from ipe::Stream
virtual ~Stream ()
virtual void putString (String s)
virtual void putCString (const char *s)
virtual void putRaw (const char *data, int size)
Streamoperator<< (char ch)
Streamoperator<< (const String &s)
Streamoperator<< (const char *s)
Streamoperator<< (int i)
Streamoperator<< (double d)
void putHexByte (char b)
void putXmlString (String s)

Static Public Member Functions

static Buffer deflate (const char *data, int size, int &deflatedSize, int compressLevel)

Detailed Description

Filter stream adding flate compression.

Constructor & Destructor Documentation

DeflateStream::DeflateStream ( Stream stream,
int  level 
)
DeflateStream::~DeflateStream ( )
virtual

Member Function Documentation

void DeflateStream::putChar ( char  ch)
virtual

Output character.

Implements ipe::Stream.

void DeflateStream::close ( )
virtual

Close the stream. No more writing allowed!

Reimplemented from ipe::Stream.

Buffer DeflateStream::deflate ( const char *  data,
int  size,
int &  deflatedSize,
int  compressLevel 
)
static

Deflate a buffer in a single run.

The returned buffer may be larger than necessary: deflatedSize is set to the number of bytes actually used.


The documentation for this class was generated from the following files:
  • ipeutils.h
  • ipeutils.cpp

ipe-7.1.4/build/doc/manual_17.html0000644000175000017500000001621212120621776016476 0ustar otfriedotfried Ipe Manual -- 4.2 Text objects
4.3 Image objects4 Object types4.1 Path objects4.2 Text objects

4.2 Text objects

Text objects come in two flavors: simple labels, and minipages. There are two variants of these: titles (a label that serves as the title of the page), and textbox (a minipage that spans the entire width of the page).

The position you have to click to start creating a label object is normally the leftmost baseline point (but this can be changed by changing the object's horizontal and vertical alignment). A popup window appears where you can enter Latex source code.

A minipage object is different from a simple text object in that its width is part of its definition. When you create a minipage object, you first have to drag out a horizontal segment for the minipage. This is used as the top edge of the minipage—it will extend downwards as far as necessary to accomodate all the text. Minipages are formatted using, not surprisingly, Latex's minipage environment. Latex tries to fill the given bounding box as nicely as possible. It is possible to include center environments, lemmas, and much more in minipages.

To create a textbox object, simply press F10. Ipe automatically places the object so that it spans the entire width of the page (the layout settings in the stylesheet determine how much space is left on the sides), and places it vertically underneath the textboxes already on the page. This is particularly convenient for creating presentations with a lot of text, or with items that appear one by one.

Title objects are managed by Ipe automatically. They are special labels that are created using Edit title & sections in the Page menu. Their color, size, alignment, and position on the page is determined by the stylesheet.

You can use any LaTeX-command that is legal inside a \makebox (for labels) or inside a minipage (for minipages). You cannot use commands that involve a non-linear translation into PDF, such as commands to generate hyperlinks or to include external images.

You can use color in your text objects, using the \textcolor command, like this:

This is in black. \textcolor{red}{This is in red.} This is in black.
All the symbolic colors of your current stylesheet are also available as arguments to \textcolor. You can also use absolute colors, for instance:
This is in black. \textcolor[rgb]{1,1,0}{This is in yellow.} This is in black.

If you need LaTeX-commands that are defined in additional LaTeX packages, you can include (\usepackage) those in the LaTeX preamble, which can be set in Document properties in the Edit menu.

After you have created or edited a text object, the Ipe screen display will show the beginning of the Latex source. You can select Run Latex from the File menu to create the PDF/Postscript representation of the object. This converts all the text objects in your document at once, and Ipe will display a correct rendition of the text afterwards.

If the Latex conversion process results in errors, Ipe will automatically show you the log file created by the Latex run. If you cannot figure out the problem, look in the section on troubleshooting.

You can use Unicode text, such as accented characters, Greek, Cyrillic, Chinese, Japanese, or Korean, in your text objects, once you have set up the necessary style files and fonts.

When Ipe computes the bounding box for a piece of text, it relies entirely on the dimensions that Latex provides. Sometimes glyphs are larger than their "official" dimensions, and as a result this bounding box is too tight. In the following figure, "A" and "G" stick out of the golden rectangle (the bounding box computed by Ipe based on the Latex dimensions) at the top, "y" sticks out at the bottom:

When you experience that text in your figures is clipped, you may have to enlarge the figure's bounding box using a "BBOX" layer.

The opposite problem can occur when you use transformed text. Ipe computes the bounding box for the transformed text by transforming the bounding box for the original text, and the result can be too large:

If this is a problem, you can put the text object inside a group and set a clipping path for the group.
ipe-7.1.4/build/doc/manual_23.html0000644000175000017500000000712012120621776016471 0ustar otfriedotfried Ipe Manual -- 5.2 Context snapping
5.3 Angular snapping5 Snapping5.1 Grid snapping5.2 Context snapping

5.2 Context snapping

When context snapping is enabled, certain features of the objects of your current drawing become magnetic. There are three buttons to enable three different features of your objects: vertices, the boundary, and intersection points.

When the mouse is too far away from the nearest interesting feature, the mouse position will not be "snapped". The snapping distance can be changed by setting Snapping distance value in the preference dialog. If you use a high setting, you will need to toggle snapping on and off during drawing. Some people prefer to set snapping on once and for all, and to set the snap distance to a very small value like 3 or 4.

The features that you can make "magnetic" are the following:

 

vertices
are vertices of polygonal objects, control points of multiplicity three of splines, centers of circles and ellipses, centers and end points of circular arcs, and mark positions.

 

boundaries
are the object boundaries of polygonal objects, splines and splinegons, circles and ellipses, and circular arcs.

 

intersections
are the intersection points between the boundaries of path objects.
ipe-7.1.4/build/doc/structipe_1_1_font-members.html0000644000175000017500000001472012120621776022054 0ustar otfriedotfried Ipelib: Member List
ipe::Font Member List

ipe-7.1.4/build/doc/classipe_1_1_pdf_dict-members.html0000644000175000017500000001722012120621776022441 0ustar otfriedotfried Ipelib: Member List
ipe::PdfDict Member List

This is the complete list of members for ipe::PdfDict, including all inherited members.

add(String key, const PdfObj *obj)ipe::PdfDict
array() const ipe::PdfObjvirtual
boolean() const ipe::PdfObjvirtual
count() const ipe::PdfDictinline
deflated() const ipe::PdfDict
dict() const ipe::PdfDictvirtual
get(String key, const PdfFile *file) const ipe::PdfDict
key(int index) const ipe::PdfDictinline
name() const ipe::PdfObjvirtual
null() const ipe::PdfObjvirtual
number() const ipe::PdfObjvirtual
PdfDict()ipe::PdfDictinlineexplicit
ref() const ipe::PdfObjvirtual
repr() const ipe::PdfObj
setStream(const Buffer &stream)ipe::PdfDict
stream() const ipe::PdfDictinline
string() const ipe::PdfObjvirtual
write(Stream &stream) const ipe::PdfDictvirtual
~PdfDict()ipe::PdfDict
~PdfObj()=0ipe::PdfObjpure virtual

ipe-7.1.4/build/doc/classipe_1_1_image-members.html0000644000175000017500000003644012120621776021754 0ustar otfriedotfried Ipelib: Member List
ipe::Image Member List

This is the complete list of members for ipe::Image, including all inherited members.

accept(Visitor &visitor) const ipe::Imagevirtual
addToBBox(Rect &box, const Matrix &m, bool) const ipe::Imagevirtual
asGroup()ipe::Objectvirtual
asImage()ipe::Imagevirtual
asPath()ipe::Objectvirtual
asReference()ipe::Objectvirtual
asText()ipe::Objectvirtual
bitmap() const ipe::Imageinline
checkStyle(const Cascade *sheet, AttributeSeq &seq) const ipe::Objectvirtual
checkSymbol(Kind kind, Attribute attr, const Cascade *sheet, AttributeSeq &seq)ipe::Objectprotectedstatic
clone() const ipe::Imagevirtual
distance(const Vector &v, const Matrix &m, double bound) const ipe::Imagevirtual
draw(Painter &painter) const ipe::Imagevirtual
drawSimple(Painter &painter) const ipe::Imagevirtual
EGroup enum valueipe::Object
EImage enum valueipe::Object
EPath enum valueipe::Object
EReference enum valueipe::Object
EText enum valueipe::Object
getAttribute(Property prop)ipe::Objectvirtual
Image(const Rect &rect, Bitmap bitmap)ipe::Imageexplicit
Image(const XmlAttributes &attr, String data)ipe::Imageexplicit
Image(const XmlAttributes &attr, Bitmap bitmap)ipe::Imageexplicit
iMatrixipe::Objectprotected
iPinnedipe::Objectprotected
iTransformationsipe::Objectprotected
matrix() const ipe::Objectinline
Object()ipe::Objectexplicitprotected
Object(const AllAttributes &attr)ipe::Objectexplicitprotected
Object(const Object &rhs)ipe::Objectprotected
Object(const XmlAttributes &attr)ipe::Objectexplicitprotected
pinned() const ipe::Objectvirtual
rect() const ipe::Imageinline
saveAsXml(Stream &stream, String layer) const ipe::Imagevirtual
saveAttributesAsXml(Stream &stream, String layer) const ipe::Objectprotected
setAttribute(Property prop, Attribute value, Attribute stroke, Attribute fill)ipe::Objectvirtual
setMatrix(const Matrix &matrix)ipe::Object
setPinned(TPinned pin)ipe::Object
setTransformations(TTransformations trans)ipe::Object
snapBnd(const Vector &mouse, const Matrix &m, Vector &pos, double &bound) const ipe::Objectvirtual
snapVtx(const Vector &mouse, const Matrix &m, Vector &pos, double &bound) const ipe::Imagevirtual
transformations() const ipe::Objectinline
Type enum nameipe::Object
type() const ipe::Imagevirtual
~Object()=0ipe::Objectpure virtual

ipe-7.1.4/build/doc/classipe_1_1_path.html0000644000175000017500000022333212120621776020174 0ustar otfriedotfried Ipelib: ipe::Path Class Reference

#include <ipepath.h>

Inherits ipe::Object.

Public Member Functions

 Path (const AllAttributes &attr, const Shape &shape, bool withArrows=false)
virtual Objectclone () const
virtual PathasPath ()
virtual Type type () const
void setPathMode (TPathMode pm)
void setStroke (Attribute stroke)
void setFill (Attribute fill)
void setPen (Attribute pen)
void setDashStyle (Attribute dash)
void setLineCap (TLineCap s)
void setLineJoin (TLineJoin s)
void setFillRule (TFillRule s)
void setOpacity (Attribute opaq)
void setTiling (Attribute a)
void setGradient (Attribute a)
Attribute opacity () const
Attribute tiling () const
Attribute gradient () const
TPathMode pathMode () const
Attribute stroke () const
Attribute fill () const
Attribute pen () const
Attribute dashStyle () const
TLineCap lineCap () const
TLineJoin lineJoin () const
TFillRule fillRule () const
virtual void saveAsXml (Stream &stream, String layer) const
virtual void draw (Painter &painter) const
virtual void drawSimple (Painter &painter) const
virtual void accept (Visitor &visitor) const
virtual void addToBBox (Rect &box, const Matrix &m, bool cp) const
virtual double distance (const Vector &v, const Matrix &m, double bound) const
virtual void snapVtx (const Vector &mouse, const Matrix &m, Vector &pos, double &bound) const
virtual void snapBnd (const Vector &mouse, const Matrix &m, Vector &pos, double &bound) const
virtual void checkStyle (const Cascade *sheet, AttributeSeq &seq) const
virtual bool setAttribute (Property prop, Attribute value, Attribute stroke, Attribute fill)
virtual Attribute getAttribute (Property prop)
bool arrow () const
bool rArrow () const
Attribute arrowShape () const
Attribute rArrowShape () const
Attribute arrowSize () const
Attribute rArrowSize () const
void setArrow (bool arrow, Attribute shape, Attribute size)
void setRarrow (bool arrow, Attribute shape, Attribute size)
const Shapeshape () const
void setShape (const Shape &shape)
- Public Member Functions inherited from ipe::Object
virtual ~Object ()=0
virtual GroupasGroup ()
virtual TextasText ()
virtual ImageasImage ()
virtual ReferenceasReference ()
virtual TPinned pinned () const
void setPinned (TPinned pin)
TTransformations transformations () const
void setTransformations (TTransformations trans)
void setMatrix (const Matrix &matrix)
const Matrixmatrix () const

Static Public Member Functions

static Pathcreate (const XmlAttributes &attr, String data)
static void drawArrow (Painter &painter, Vector pos, Angle alpha, Attribute shape, Attribute size, double radius)

Additional Inherited Members

- Public Types inherited from ipe::Object
enum  Type {
  EGroup, EPath, EText, EImage,
  EReference
}
- Protected Member Functions inherited from ipe::Object
 Object ()
 Object (const AllAttributes &attr)
 Object (const Object &rhs)
 Object (const XmlAttributes &attr)
void saveAttributesAsXml (Stream &stream, String layer) const
- Static Protected Member Functions inherited from ipe::Object
static void checkSymbol (Kind kind, Attribute attr, const Cascade *sheet, AttributeSeq &seq)
- Protected Attributes inherited from ipe::Object
Matrix iMatrix
TPinned iPinned: 8
TTransformations iTransformations: 8

Detailed Description

The path object (polylines, polygons, and generalizations).

This object represents any vector graphics. The geometry is contained in a Shape.

The filling algorithm is the even-odd rule of PDF: To determine whether a point lies inside the filled shape, draw a ray from that point in any direction, and count the number of path segments that cross the ray. If this number is odd, the point is inside; if even, the point is outside. (Path objects can also render using the winding fill rule by setting the fillRule attribute. This isn't really supported by the Ipe user interface, which doesn't show the orientation of paths.)

If the path consists of a single line segment and is filled only, then it is not drawn at all. This can be used to draw arrow heads without bodies. The fill color is used to draw the arrows in this case.

Constructor & Destructor Documentation

Path::Path ( const AllAttributes attr,
const Shape shape,
bool  withArrows = false 
)
explicit

Create for given shape.

Member Function Documentation

Path * Path::create ( const XmlAttributes attr,
String  data 
)
static

Construct from XML data.

Object * Path::clone ( ) const
virtual

Return a clone (constant-time).

Implements ipe::Object.

Path * Path::asPath ( )
virtual

Return pointer to this object.

Reimplemented from ipe::Object.

Object::Type Path::type ( ) const
virtual

Implements ipe::Object.

void Path::setPathMode ( TPathMode  pm)

Set whether object will be stroked and filled.

void Path::setStroke ( Attribute  stroke)

Set stroke color.

void Path::setFill ( Attribute  fill)

Set fill color.

void Path::setPen ( Attribute  pen)

Set pen.

void Path::setDashStyle ( Attribute  dash)

Set dash style.

void Path::setLineCap ( TLineCap  s)

Set line cap style.

void Path::setLineJoin ( TLineJoin  s)

Set line join style.

void Path::setFillRule ( TFillRule  s)

Set fill rule.

void Path::setOpacity ( Attribute  opaq)

Set opacity of the object.

void Path::setTiling ( Attribute  til)

Set tiling pattern of the object.

Resets gradient fill.

void Path::setGradient ( Attribute  grad)

Set gradient fill of the object.

Resets tiling pattern.

Attribute ipe::Path::opacity ( ) const
inline

Return opacity of the opject.

Attribute ipe::Path::tiling ( ) const
inline

Return tiling pattern.

Attribute ipe::Path::gradient ( ) const
inline

Return gradient fill.

TPathMode ipe::Path::pathMode ( ) const
inline

Is the object stroked and filled?

Attribute ipe::Path::stroke ( ) const
inline

Return stroke color.

Attribute ipe::Path::fill ( ) const
inline

Return object fill color.

Attribute ipe::Path::pen ( ) const
inline

Return object pen.

Attribute ipe::Path::dashStyle ( ) const
inline

Return object line style.

TLineCap ipe::Path::lineCap ( ) const
inline

Return line cap style.

TLineJoin ipe::Path::lineJoin ( ) const
inline

Return line join style.

TFillRule ipe::Path::fillRule ( ) const
inline

Return fill rule.

void Path::saveAsXml ( Stream stream,
String  layer 
) const
virtual

Save the object in XML format.

Implements ipe::Object.

void Path::draw ( Painter painter) const
virtual

Draw the object.

Implements ipe::Object.

void Path::drawSimple ( Painter painter) const
virtual

Draw simple version for selecting and transforming.

Implements ipe::Object.

void Path::accept ( Visitor visitor) const
virtual

Call visitPath of visitor.

Implements ipe::Object.

void Path::addToBBox ( Rect box,
const Matrix m,
bool  cp 
) const
virtual

Extend box to include the object transformed by m.

For objects in a page, don't call this directly. The Page caches the bounding box of each object, so it is far more efficient to call Page::bbox.

Control points that lie outside the visual object are included if cp is true.

If called with an empty box and cp == false, the result of this function is a tight bounding box for the object, with a little leeway in case the boundary is determined by a spline (it has to be approximated to perform this operation).

Implements ipe::Object.

double Path::distance ( const Vector v,
const Matrix m,
double  bound 
) const
virtual

Return distance of transformed object to point v. If larger than bound, can just return bound.

Implements ipe::Object.

void Path::snapVtx ( const Vector mouse,
const Matrix m,
Vector pos,
double &  bound 
) const
virtual

Compute possible vertex snapping position for transformed object.

Looks only for positions closer than bound. If successful, modify pos and bound.

Implements ipe::Object.

void Path::snapBnd ( const Vector mouse,
const Matrix m,
Vector pos,
double &  bound 
) const
virtual

Compute boundary snapping position for transformed object.

Looks only for positions closer than bound. If successful, modify pos and bound. The default implementation does nothing.

Reimplemented from ipe::Object.

void Path::checkStyle ( const Cascade sheet,
AttributeSeq seq 
) const
virtual

Check all symbolic attributes.

Reimplemented from ipe::Object.

bool Path::setAttribute ( Property  prop,
Attribute  value,
Attribute  stroke,
Attribute  fill 
)
virtual

Set an attribute on this object.

Returns true if an attribute was actually changed. The arguments stroke and fill are only used then prop is EPropPathMode, and stroking or filling is added to an object that didn't have it before.

Reimplemented from ipe::Object.

Attribute Path::getAttribute ( Property  prop)
virtual

Get setting of an attribute of this object.

If object does not have this attribute, returnes "undefined" attribute.

Reimplemented from ipe::Object.

bool ipe::Path::arrow ( ) const
inline

Does object have an arrow?

bool ipe::Path::rArrow ( ) const
inline

Does object have a reverse arrow?

Attribute ipe::Path::arrowShape ( ) const
inline

Return shape of arrow.

Attribute ipe::Path::rArrowShape ( ) const
inline

Return shape of reverse arrow.

Attribute ipe::Path::arrowSize ( ) const
inline

Return size of arrow.

Attribute ipe::Path::rArrowSize ( ) const
inline

Return size of reverse arrow.

void Path::setArrow ( bool  arrow,
Attribute  shape,
Attribute  size 
)

Set forward arrow.

void Path::setRarrow ( bool  arrow,
Attribute  shape,
Attribute  size 
)

Set backward arrow (if the object can take it).

void Path::drawArrow ( Painter painter,
Vector  pos,
Angle  angle,
Attribute  shape,
Attribute  size,
double  radius 
)
static

Draw an arrow of size with tip at pos directed in direction angle.

const Shape& ipe::Path::shape ( ) const
inline

Return shape of the path object.

void Path::setShape ( const Shape shape)

The documentation for this class was generated from the following files:
  • ipepath.h
  • ipepath.cpp

ipe-7.1.4/build/doc/classipe_1_1_lex-members.html0000644000175000017500000001417312120621776021461 0ustar otfriedotfried Ipelib: Member List
ipe::Lex Member List

This is the complete list of members for ipe::Lex, including all inherited members.

eos() const ipe::Lexinline
fromMark()ipe::Lexinline
getChar()ipe::Lexinline
getDouble()ipe::Lex
getFixed()ipe::Lex
getHexByte()ipe::Lex
getHexNumber()ipe::Lex
getInt()ipe::Lex
Lex(String str)ipe::Lexexplicit
mark()ipe::Lexinline
nextToken()ipe::Lex
operator>>(int &i)ipe::Lexinline
operator>>(double &d)ipe::Lexinline
operator>>(Fixed &d)ipe::Lexinline
skipWhitespace()ipe::Lex
token()ipe::Lex

ipe-7.1.4/build/doc/classipe_1_1_transform_tool.html0000644000175000017500000006156212120621776022315 0ustar otfriedotfried Ipelib: ipe::TransformTool Class Reference

#include <ipetool.h>

Inherits ipe::Tool.

Public Types

enum  TType { ETranslate, EScale, EStretch, ERotate }

Public Member Functions

 TransformTool (CanvasBase *canvas, Page *page, int view, TType type, bool withShift)
bool isValid () const
virtual void draw (Painter &painter) const
virtual void mouseButton (int button, bool press)
virtual void mouseMove ()
virtual void report ()
- Public Member Functions inherited from ipe::Tool
virtual ~Tool ()
virtual bool key (int code, int modifiers, String text)

Protected Member Functions

void compute (const Vector &v)
- Protected Member Functions inherited from ipe::Tool
 Tool (CanvasBase *canvas)

Protected Attributes

PageiPage
int iView
TType iType
bool iWithShift
bool iOnlyHorizontal
bool iOnlyVertical
Vector iMouseDown
Matrix iTransform
Vector iOrigin
bool iValid
- Protected Attributes inherited from ipe::Tool
CanvasBaseiCanvas

Detailed Description

A tool for transforming the selected objects on the canvas.

Supports moving, rotating, scaling, and stretching.

Member Enumeration Documentation

Enumerator:
ETranslate 
EScale 
EStretch 
ERotate 

Constructor & Destructor Documentation

TransformTool::TransformTool ( CanvasBase canvas,
Page page,
int  view,
TType  type,
bool  withShift 
)

Constructor starts transformation.

After constructing a TransformTool, you must call isValid() to ensure that the transformation can be performed.

A transformation can fail because the selection contains pinned objects, or because the initial mouse position is identical to the transformation origin.

Member Function Documentation

bool TransformTool::isValid ( ) const

Check that the transformation can be performed.

void TransformTool::draw ( Painter painter) const
virtual

Implements ipe::Tool.

void TransformTool::mouseButton ( int  button,
bool  press 
)
virtual

Called when a mouse button is pressed or released on the canvas.

button is 1, 2, or 3, with Shift/Ctrl/Alt/Meta modifiers added in (as defined in CanvasBase::TModifiers. press is true for button-down, and false for button-up.

Reimplemented from ipe::Tool.

void TransformTool::mouseMove ( )
virtual

Called when the mouse is moved on the canvas.

Reimplemented from ipe::Tool.

void TransformTool::report ( )
virtual

Report the final transformation chosen.

The implementation in TransformTool does nothing. Derived classes should reimplement report().

void TransformTool::compute ( const Vector v)
protected

Member Data Documentation

Page* ipe::TransformTool::iPage
protected
int ipe::TransformTool::iView
protected
TType ipe::TransformTool::iType
protected
bool ipe::TransformTool::iWithShift
protected
bool ipe::TransformTool::iOnlyHorizontal
protected
bool ipe::TransformTool::iOnlyVertical
protected
Vector ipe::TransformTool::iMouseDown
protected
Matrix ipe::TransformTool::iTransform
protected
Vector ipe::TransformTool::iOrigin
protected
bool ipe::TransformTool::iValid
protected

The documentation for this class was generated from the following files:
  • ipetool.h
  • ipetool.cpp

ipe-7.1.4/build/doc/classipe_1_1_file_stream.html0000644000175000017500000002242512120621776021532 0ustar otfriedotfried Ipelib: ipe::FileStream Class Reference
ipe::FileStream Class Reference

#include <ipebase.h>

Inherits ipe::TellStream.

Public Member Functions

 FileStream (std::FILE *file)
virtual void putChar (char ch)
virtual void putString (String s)
virtual void putCString (const char *s)
virtual void putRaw (const char *data, int size)
virtual long tell () const

Detailed Description

Stream writing into an open file.

Constructor & Destructor Documentation

FileStream::FileStream ( std::FILE *  file)

Constructor.

Member Function Documentation

void FileStream::putChar ( char  ch)
virtual

Output character.

Implements ipe::Stream.

void FileStream::putString ( String  s)
virtual

Output string.

Default implementation uses PutChar.

Reimplemented from ipe::Stream.

void FileStream::putCString ( const char *  s)
virtual

Output C string.

Default implementation uses PutChar.

Reimplemented from ipe::Stream.

void FileStream::putRaw ( const char *  data,
int  size 
)
virtual

Output raw character data.

Default implementation uses PutChar.

Reimplemented from ipe::Stream.

long FileStream::tell ( ) const
virtual

Implements ipe::TellStream.


The documentation for this class was generated from the following files:
  • ipebase.h
  • ipebase.cpp

ipe-7.1.4/build/doc/structipe_1_1_ipelet_data-members.html0000644000175000017500000000765712120621776023374 0ustar otfriedotfried Ipelib: Member List
ipe::IpeletData Member List

ipe-7.1.4/build/doc/functions_func.html0000644000175000017500000003240412120621776017736 0ustar otfriedotfried Ipelib: Class Members - Functions
 

- a -


ipe-7.1.4/readme.txt0000644000175000017500000001022112120621776014150 0ustar otfriedotfriedIpe 7.1.4 March, 2013 Ipe extensible drawing editor ============================= Introduction ============ This is the extensible drawing editor Ipe. Ipe allows you to create figures in PDF format, for inclusion into LaTeX (or plain TeX) documents as well as stand-alone PDF documents, for instance to print transparencies or for on-line presentations. See the manual for an introduction. It is available in both HTML ("build/doc/manual.html") and PDF format ("build/doc/manual.pdf"). If you have used Ipe 6 up to now and this is your first contact with Ipe 7, you should read the (short) manual section about upgrading to Ipe 7. The separate file "install.txt" explains how to build and install Ipe on Unix. Ipe is also available for Windows in the form of a zip archive. On Windows, all you need to do is unzip the archive, and you are ready to run. (If you do want to compile on Windows yourself, it's not difficult - based on the Unix instructions you should be able to work it out.) -------------------------------------------------------------------- This file is part of the extensible drawing editor Ipe. Copyright (C) 1993-2013 Otfried Cheong Ipe is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. As a special exception, you have permission to link Ipe with the CGAL library and distribute executables, as long as you follow the requirements of the Gnu General Public License in regard to all of the software in the executable aside from CGAL. Ipe 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 General Public License for more details. You should have received a copy of the GNU General Public License along with Ipe; if not, you can find it at "http://www.gnu.org/copyleft/gpl.html", or write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. -------------------------------------------------------------------- Ipe uses the Zlib library (www.gzip.org/zlib), the Freetype 2 library (www.freetype.org), the Cairo library (www.cairographics.org), as well as some code from Xpdf (www.foolabs.com/xpdf). Ipe contains the Lua 5.2 interpreter (www.lua.org), and uses the Qt toolkit for its graphical user interface (qt.digia.com). Ipe relies on Pdflatex for rendering text. -------------------------------------------------------------------- Before reporting a bug, check that you have the latest version, and check that it is not yet mentioned in the FAQ on the Ipe webpage. You can report bugs on the bug tracking system at "http://ipe7.sourceforge.net/bugzilla.html". Check the existing reports to see whether your bug has already been reported. Please do not send bug reports directly to me (the first thing I would do with the report is to enter it into the bug tracking system). Suggestions for features, or random comments on Ipe can be sent to the Ipe discussion mailing list at . If you have problems installing or using Ipe and cannot find a guru among your real-life friends, the Ipe discussion mailing list would also be the best place to ask. You can send suggestions or comments directly to me by Email, but you should then not expect a reply. I cannot dedicate much time to Ipe, and the little time I have I prefer to put into development. I'm much more likely to get involved in a discussion of desirable features on the mailing list, where anyone interested can participate, rather than by direct Email. If you write interesting ipelets that might be useful to others, please put a link or copy (as you prefer) on the Ipe wiki. Feel free to advertise them on the Ipe discussion list! Otfried Cheong Dept. of Computer Science KAIST Daejeon, South Korea Email: otfried@ipe.airpost.net Ipe webpage: http://ipe7.sourceforge.net -------------------------------------------------------------------- ipe-7.1.4/scripts/0000755000175000017500000000000012120621776013645 5ustar otfriedotfriedipe-7.1.4/scripts/update-master.lua0000644000175000017500000000537312120621776017133 0ustar otfriedotfried#!/usr/bin/env ipescript -- -*- lua -*- ---------------------------------------------------------------------- -- Update master-preamble stylesheet ---------------------------------------------------------------------- -- -- When using Ipe figures in a Latex document, it is convenient -- to have access to some of the definitions from the document. -- -- This Lua script makes this easy: In your Latex document -- (e.g. master.tex), surround the interesting definitions using -- %%BeginIpePreamble and %%EndIpePreamble, e.g. like this: -- -- %%BeginIpePreamble -- \usepackage{amsfonts} -- \newcommand{\R}{\mathbb{R}} -- %%EndIpePreamble -- -- Running this script as "ipescript update-master master.tex" will -- extract the Ipe definitions, and save them as a stylesheet -- "master-preamble.isy" -- -- Running this script as "ipescript update-master master.tex figures/*.ipe" -- will in addition look at all the Ipe figures, and either add -- "master-preamble.isy" to it, or update the stylesheet to the newest -- version. -- ---------------------------------------------------------------------- if #argv == 0 then io.stderr:write("Usage: ipescript update-master [ ]\n") return end local texname = argv[1] local fignames = argv table.remove(fignames, 1) local f = io.open(texname, "r") text = f:read("*all") f:close() local mat = text:match("%%%%BeginIpePreamble(.*)%%%%EndIpePreamble") if not mat then io.stderr:write("No Ipe definitions found in '" .. texname .. "'\n") return end local out = io.open("master-preamble.isy", "w") out:write('\n\n') out:write(mat) out:write("\n\n") out:close() local nsheet = assert(ipe.Sheet("master-preamble.isy")) io.stderr:write("Extracted definitions and created 'master-preamble.isy'\n") for _,figname in ipairs(fignames) do io.stderr:write("Checking figure '" .. figname .. "'\n") local doc = assert(ipe.Document(figname)) local index = nil for i=1,doc:sheets():count() do local sheet = doc:sheets():sheet(i) if sheet:name() == "master-preamble" then index = i break end end if index then io.stderr:write("Found 'master-preamble' stylesheet, updating it.\n") doc:sheets():insert(index, nsheet:clone()) doc:sheets():remove(index + 1) -- remove old copy else io.stderr:write("Adding 'master-preamble' stylesheet.\n") doc:sheets():insert(1, nsheet:clone()) end if figname:sub(-4) ~= ".ipe" and figname:sub(-4) ~= ".xml" then assert(doc:runLatex()) end -- make a backup of original local f = assert(io.open(figname, "rb")) local data = f:read("*all") f:close() f = assert(io.open(figname .. ".bak", "wb")) f:write(data) f:close() -- now write updated figure back doc:save(figname) end ipe-7.1.4/scripts/update-styles.lua0000644000175000017500000000515212120621776017156 0ustar otfriedotfried#!/usr/bin/env ipescript -- -*- lua -*- ---------------------------------------------------------------------- -- Update stylesheets in Ipe documents ---------------------------------------------------------------------- -- -- Running this script as "ipescript update-styles " will -- update the stylesheets in the Ipe figures given. -- -- To update a stylesheet, the script will look for a file with the -- same name as the stylesheet plus the extension ".isy". It searches -- for this file in the current directory, plus all the directories -- given in the IPESTYLES environment variable (with the same default -- settings as in Ipe). -- ---------------------------------------------------------------------- local ipestyles = os.getenv("IPESTYLES") local home = os.getenv("HOME") if ipestyles then styleDirs = { "." } for w in string.gmatch(ipestyles, "[^:;]+") do if w == "_" then w = config.system_styles end styleDirs[#styleDirs + 1] = w end else styleDirs = { ".", config.system_styles } if config.platform ~= "win" then table.insert(styleDirs, 2, home .. "/.ipe/styles") if config.platform == "apple" then table.insert(styleDirs, 3, home .. "/Library/Ipe/Styles") end end end function findStyle(w) for _, d in ipairs(styleDirs) do local s = d .. "/" .. w if ipe.fileExists(s) then return s end end end -------------------------------------------------------------------- if #argv == 0 then io.stderr:write("Usage: ipescript update-styles \n") return end local fignames = argv for _,figname in ipairs(fignames) do io.stderr:write("Updating styles in figure '" .. figname .. "'\n") local doc = assert(ipe.Document(figname)) for index=1,doc:sheets():count() do local sheet = doc:sheets():sheet(index) local name = sheet:name() if not name then io.stderr:write(" - unnamed stylesheet\n") elseif name == "standard" then io.stderr:write(" - standard stylesheet\n") else io.stderr:write(" - stylesheet '" .. name .. "'\n") local s = findStyle(name .. ".isy") if s then io.stderr:write(" updating from '" .. s .."'\n") local nsheet = assert(ipe.Sheet(s)) doc:sheets():insert(index, nsheet) doc:sheets():remove(index + 1) -- remove old sheet end end end if figname:sub(-4) ~= ".ipe" and figname:sub(-4) ~= ".xml" then assert(doc:runLatex()) end -- make a backup of original figure local f = assert(io.open(figname, "rb")) local data = f:read("*all") f:close() f = assert(io.open(figname .. ".bak", "wb")) f:write(data) f:close() -- now write updated figure back doc:save(figname) end ipe-7.1.4/scripts/add-style.lua0000644000175000017500000000165512120621776016245 0ustar otfriedotfried#!/usr/bin/env ipescript -- -*- lua -*- ---------------------------------------------------------------------- -- Add stylesheet ---------------------------------------------------------------------- -- -- Run this script as "ipescript add-style
" -- -- It adds the stylesheet to the Ipe document
. -- ---------------------------------------------------------------------- if #argv ~= 2 then io.stderr:write("Usage: ipescript add-style
\n") return end local sheetname = argv[1] local figname = argv[2] local nsheet = assert(ipe.Sheet(sheetname)) local doc = assert(ipe.Document(figname)) doc:sheets():insert(1, nsheet) assert(doc:runLatex()) -- make a backup of original local f = assert(io.open(figname, "rb")) local data = f:read("*all") f:close() f = assert(io.open(figname .. ".bak", "wb")) f:write(data) f:close() -- now write updated figure back doc:save(figname) ipe-7.1.4/gpl.txt0000644000175000017500000010451312120621776013505 0ustar otfriedotfried GNU GENERAL PUBLIC LICENSE Version 3, 29 June 2007 Copyright (C) 2007 Free Software Foundation, Inc. Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. Preamble The GNU General Public License is a free, copyleft license for software and other kinds of works. The licenses for most software and other practical works are designed to take away your freedom to share and change the works. By contrast, the GNU General Public License is intended to guarantee your freedom to share and change all versions of a program--to make sure it remains free software for all its users. We, the Free Software Foundation, use the GNU General Public License for most of our software; it applies also to any other work released this way by its authors. You can apply it to your programs, too. When we speak of free software, we are referring to freedom, 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 them if you wish), that you receive source code or can get it if you want it, that you can change the software or use pieces of it in new free programs, and that you know you can do these things. To protect your rights, we need to prevent others from denying you these rights or asking you to surrender the rights. Therefore, you have certain responsibilities if you distribute copies of the software, or if you modify it: responsibilities to respect the freedom of others. For example, if you distribute copies of such a program, whether gratis or for a fee, you must pass on to the recipients the same freedoms that you received. You must make sure that they, too, receive or can get the source code. And you must show them these terms so they know their rights. Developers that use the GNU GPL protect your rights with two steps: (1) assert copyright on the software, and (2) offer you this License giving you legal permission to copy, distribute and/or modify it. For the developers' and authors' protection, the GPL clearly explains that there is no warranty for this free software. For both users' and authors' sake, the GPL requires that modified versions be marked as changed, so that their problems will not be attributed erroneously to authors of previous versions. Some devices are designed to deny users access to install or run modified versions of the software inside them, although the manufacturer can do so. This is fundamentally incompatible with the aim of protecting users' freedom to change the software. The systematic pattern of such abuse occurs in the area of products for individuals to use, which is precisely where it is most unacceptable. Therefore, we have designed this version of the GPL to prohibit the practice for those products. If such problems arise substantially in other domains, we stand ready to extend this provision to those domains in future versions of the GPL, as needed to protect the freedom of users. Finally, every program is threatened constantly by software patents. States should not allow patents to restrict development and use of software on general-purpose computers, but in those that do, we wish to avoid the special danger that patents applied to a free program could make it effectively proprietary. To prevent this, the GPL assures that patents cannot be used to render the program non-free. The precise terms and conditions for copying, distribution and modification follow. TERMS AND CONDITIONS 0. Definitions. "This License" refers to version 3 of the GNU General Public License. "Copyright" also means copyright-like laws that apply to other kinds of works, such as semiconductor masks. "The Program" refers to any copyrightable work licensed under this License. Each licensee is addressed as "you". "Licensees" and "recipients" may be individuals or organizations. To "modify" a work means to copy from or adapt all or part of the work in a fashion requiring copyright permission, other than the making of an exact copy. The resulting work is called a "modified version" of the earlier work or a work "based on" the earlier work. A "covered work" means either the unmodified Program or a work based on the Program. To "propagate" a work means to do anything with it that, without permission, would make you directly or secondarily liable for infringement under applicable copyright law, except executing it on a computer or modifying a private copy. Propagation includes copying, distribution (with or without modification), making available to the public, and in some countries other activities as well. To "convey" a work means any kind of propagation that enables other parties to make or receive copies. Mere interaction with a user through a computer network, with no transfer of a copy, is not conveying. An interactive user interface displays "Appropriate Legal Notices" to the extent that it includes a convenient and prominently visible feature that (1) displays an appropriate copyright notice, and (2) tells the user that there is no warranty for the work (except to the extent that warranties are provided), that licensees may convey the work under this License, and how to view a copy of this License. If the interface presents a list of user commands or options, such as a menu, a prominent item in the list meets this criterion. 1. Source Code. The "source code" for a work means the preferred form of the work for making modifications to it. "Object code" means any non-source form of a work. A "Standard Interface" means an interface that either is an official standard defined by a recognized standards body, or, in the case of interfaces specified for a particular programming language, one that is widely used among developers working in that language. The "System Libraries" of an executable work include anything, other than the work as a whole, that (a) is included in the normal form of packaging a Major Component, but which is not part of that Major Component, and (b) serves only to enable use of the work with that Major Component, or to implement a Standard Interface for which an implementation is available to the public in source code form. A "Major Component", in this context, means a major essential component (kernel, window system, and so on) of the specific operating system (if any) on which the executable work runs, or a compiler used to produce the work, or an object code interpreter used to run it. The "Corresponding Source" for a work in object code form means all the source code needed to generate, install, and (for an executable work) run the object code and to modify the work, including scripts to control those activities. However, it does not include the work's System Libraries, or general-purpose tools or generally available free programs which are used unmodified in performing those activities but which are not part of the work. For example, Corresponding Source includes interface definition files associated with source files for the work, and the source code for shared libraries and dynamically linked subprograms that the work is specifically designed to require, such as by intimate data communication or control flow between those subprograms and other parts of the work. The Corresponding Source need not include anything that users can regenerate automatically from other parts of the Corresponding Source. The Corresponding Source for a work in source code form is that same work. 2. Basic Permissions. All rights granted under this License are granted for the term of copyright on the Program, and are irrevocable provided the stated conditions are met. This License explicitly affirms your unlimited permission to run the unmodified Program. The output from running a covered work is covered by this License only if the output, given its content, constitutes a covered work. This License acknowledges your rights of fair use or other equivalent, as provided by copyright law. You may make, run and propagate covered works that you do not convey, without conditions so long as your license otherwise remains in force. You may convey covered works to others for the sole purpose of having them make modifications exclusively for you, or provide you with facilities for running those works, provided that you comply with the terms of this License in conveying all material for which you do not control copyright. Those thus making or running the covered works for you must do so exclusively on your behalf, under your direction and control, on terms that prohibit them from making any copies of your copyrighted material outside their relationship with you. Conveying under any other circumstances is permitted solely under the conditions stated below. Sublicensing is not allowed; section 10 makes it unnecessary. 3. Protecting Users' Legal Rights From Anti-Circumvention Law. No covered work shall be deemed part of an effective technological measure under any applicable law fulfilling obligations under article 11 of the WIPO copyright treaty adopted on 20 December 1996, or similar laws prohibiting or restricting circumvention of such measures. When you convey a covered work, you waive any legal power to forbid circumvention of technological measures to the extent such circumvention is effected by exercising rights under this License with respect to the covered work, and you disclaim any intention to limit operation or modification of the work as a means of enforcing, against the work's users, your or third parties' legal rights to forbid circumvention of technological measures. 4. Conveying Verbatim Copies. You may convey verbatim copies of the Program's source code as you receive it, in any medium, provided that you conspicuously and appropriately publish on each copy an appropriate copyright notice; keep intact all notices stating that this License and any non-permissive terms added in accord with section 7 apply to the code; keep intact all notices of the absence of any warranty; and give all recipients a copy of this License along with the Program. You may charge any price or no price for each copy that you convey, and you may offer support or warranty protection for a fee. 5. Conveying Modified Source Versions. You may convey a work based on the Program, or the modifications to produce it from the Program, in the form of source code under the terms of section 4, provided that you also meet all of these conditions: a) The work must carry prominent notices stating that you modified it, and giving a relevant date. b) The work must carry prominent notices stating that it is released under this License and any conditions added under section 7. This requirement modifies the requirement in section 4 to "keep intact all notices". c) You must license the entire work, as a whole, under this License to anyone who comes into possession of a copy. This License will therefore apply, along with any applicable section 7 additional terms, to the whole of the work, and all its parts, regardless of how they are packaged. This License gives no permission to license the work in any other way, but it does not invalidate such permission if you have separately received it. d) If the work has interactive user interfaces, each must display Appropriate Legal Notices; however, if the Program has interactive interfaces that do not display Appropriate Legal Notices, your work need not make them do so. A compilation of a covered work with other separate and independent works, which are not by their nature extensions of the covered work, and which are not combined with it such as to form a larger program, in or on a volume of a storage or distribution medium, is called an "aggregate" if the compilation and its resulting copyright are not used to limit the access or legal rights of the compilation's users beyond what the individual works permit. Inclusion of a covered work in an aggregate does not cause this License to apply to the other parts of the aggregate. 6. Conveying Non-Source Forms. You may convey a covered work in object code form under the terms of sections 4 and 5, provided that you also convey the machine-readable Corresponding Source under the terms of this License, in one of these ways: a) Convey the object code in, or embodied in, a physical product (including a physical distribution medium), accompanied by the Corresponding Source fixed on a durable physical medium customarily used for software interchange. b) Convey the object code in, or embodied in, a physical product (including a physical distribution medium), accompanied by a written offer, valid for at least three years and valid for as long as you offer spare parts or customer support for that product model, to give anyone who possesses the object code either (1) a copy of the Corresponding Source for all the software in the product that is covered by this License, on a durable physical medium customarily used for software interchange, for a price no more than your reasonable cost of physically performing this conveying of source, or (2) access to copy the Corresponding Source from a network server at no charge. c) Convey individual copies of the object code with a copy of the written offer to provide the Corresponding Source. This alternative is allowed only occasionally and noncommercially, and only if you received the object code with such an offer, in accord with subsection 6b. d) Convey the object code by offering access from a designated place (gratis or for a charge), and offer equivalent access to the Corresponding Source in the same way through the same place at no further charge. You need not require recipients to copy the Corresponding Source along with the object code. If the place to copy the object code is a network server, the Corresponding Source may be on a different server (operated by you or a third party) that supports equivalent copying facilities, provided you maintain clear directions next to the object code saying where to find the Corresponding Source. Regardless of what server hosts the Corresponding Source, you remain obligated to ensure that it is available for as long as needed to satisfy these requirements. e) Convey the object code using peer-to-peer transmission, provided you inform other peers where the object code and Corresponding Source of the work are being offered to the general public at no charge under subsection 6d. A separable portion of the object code, whose source code is excluded from the Corresponding Source as a System Library, need not be included in conveying the object code work. A "User Product" is either (1) a "consumer product", which means any tangible personal property which is normally used for personal, family, or household purposes, or (2) anything designed or sold for incorporation into a dwelling. In determining whether a product is a consumer product, doubtful cases shall be resolved in favor of coverage. For a particular product received by a particular user, "normally used" refers to a typical or common use of that class of product, regardless of the status of the particular user or of the way in which the particular user actually uses, or expects or is expected to use, the product. A product is a consumer product regardless of whether the product has substantial commercial, industrial or non-consumer uses, unless such uses represent the only significant mode of use of the product. "Installation Information" for a User Product means any methods, procedures, authorization keys, or other information required to install and execute modified versions of a covered work in that User Product from a modified version of its Corresponding Source. The information must suffice to ensure that the continued functioning of the modified object code is in no case prevented or interfered with solely because modification has been made. If you convey an object code work under this section in, or with, or specifically for use in, a User Product, and the conveying occurs as part of a transaction in which the right of possession and use of the User Product is transferred to the recipient in perpetuity or for a fixed term (regardless of how the transaction is characterized), the Corresponding Source conveyed under this section must be accompanied by the Installation Information. But this requirement does not apply if neither you nor any third party retains the ability to install modified object code on the User Product (for example, the work has been installed in ROM). The requirement to provide Installation Information does not include a requirement to continue to provide support service, warranty, or updates for a work that has been modified or installed by the recipient, or for the User Product in which it has been modified or installed. Access to a network may be denied when the modification itself materially and adversely affects the operation of the network or violates the rules and protocols for communication across the network. Corresponding Source conveyed, and Installation Information provided, in accord with this section must be in a format that is publicly documented (and with an implementation available to the public in source code form), and must require no special password or key for unpacking, reading or copying. 7. Additional Terms. "Additional permissions" are terms that supplement the terms of this License by making exceptions from one or more of its conditions. Additional permissions that are applicable to the entire Program shall be treated as though they were included in this License, to the extent that they are valid under applicable law. If additional permissions apply only to part of the Program, that part may be used separately under those permissions, but the entire Program remains governed by this License without regard to the additional permissions. When you convey a copy of a covered work, you may at your option remove any additional permissions from that copy, or from any part of it. (Additional permissions may be written to require their own removal in certain cases when you modify the work.) You may place additional permissions on material, added by you to a covered work, for which you have or can give appropriate copyright permission. Notwithstanding any other provision of this License, for material you add to a covered work, you may (if authorized by the copyright holders of that material) supplement the terms of this License with terms: a) Disclaiming warranty or limiting liability differently from the terms of sections 15 and 16 of this License; or b) Requiring preservation of specified reasonable legal notices or author attributions in that material or in the Appropriate Legal Notices displayed by works containing it; or c) Prohibiting misrepresentation of the origin of that material, or requiring that modified versions of such material be marked in reasonable ways as different from the original version; or d) Limiting the use for publicity purposes of names of licensors or authors of the material; or e) Declining to grant rights under trademark law for use of some trade names, trademarks, or service marks; or f) Requiring indemnification of licensors and authors of that material by anyone who conveys the material (or modified versions of it) with contractual assumptions of liability to the recipient, for any liability that these contractual assumptions directly impose on those licensors and authors. All other non-permissive additional terms are considered "further restrictions" within the meaning of section 10. If the Program as you received it, or any part of it, contains a notice stating that it is governed by this License along with a term that is a further restriction, you may remove that term. If a license document contains a further restriction but permits relicensing or conveying under this License, you may add to a covered work material governed by the terms of that license document, provided that the further restriction does not survive such relicensing or conveying. If you add terms to a covered work in accord with this section, you must place, in the relevant source files, a statement of the additional terms that apply to those files, or a notice indicating where to find the applicable terms. Additional terms, permissive or non-permissive, may be stated in the form of a separately written license, or stated as exceptions; the above requirements apply either way. 8. Termination. You may not propagate or modify a covered work except as expressly provided under this License. Any attempt otherwise to propagate or modify it is void, and will automatically terminate your rights under this License (including any patent licenses granted under the third paragraph of section 11). However, if you cease all violation of this License, then your license from a particular copyright holder is reinstated (a) provisionally, unless and until the copyright holder explicitly and finally terminates your license, and (b) permanently, if the copyright holder fails to notify you of the violation by some reasonable means prior to 60 days after the cessation. Moreover, your license from a particular copyright holder is reinstated permanently if the copyright holder notifies you of the violation by some reasonable means, this is the first time you have received notice of violation of this License (for any work) from that copyright holder, and you cure the violation prior to 30 days after your receipt of the notice. Termination of your rights under this section does not terminate the licenses of parties who have received copies or rights from you under this License. If your rights have been terminated and not permanently reinstated, you do not qualify to receive new licenses for the same material under section 10. 9. Acceptance Not Required for Having Copies. You are not required to accept this License in order to receive or run a copy of the Program. Ancillary propagation of a covered work occurring solely as a consequence of using peer-to-peer transmission to receive a copy likewise does not require acceptance. However, nothing other than this License grants you permission to propagate or modify any covered work. These actions infringe copyright if you do not accept this License. Therefore, by modifying or propagating a covered work, you indicate your acceptance of this License to do so. 10. Automatic Licensing of Downstream Recipients. Each time you convey a covered work, the recipient automatically receives a license from the original licensors, to run, modify and propagate that work, subject to this License. You are not responsible for enforcing compliance by third parties with this License. An "entity transaction" is a transaction transferring control of an organization, or substantially all assets of one, or subdividing an organization, or merging organizations. If propagation of a covered work results from an entity transaction, each party to that transaction who receives a copy of the work also receives whatever licenses to the work the party's predecessor in interest had or could give under the previous paragraph, plus a right to possession of the Corresponding Source of the work from the predecessor in interest, if the predecessor has it or can get it with reasonable efforts. You may not impose any further restrictions on the exercise of the rights granted or affirmed under this License. For example, you may not impose a license fee, royalty, or other charge for exercise of rights granted under this License, and you may not initiate litigation (including a cross-claim or counterclaim in a lawsuit) alleging that any patent claim is infringed by making, using, selling, offering for sale, or importing the Program or any portion of it. 11. Patents. A "contributor" is a copyright holder who authorizes use under this License of the Program or a work on which the Program is based. The work thus licensed is called the contributor's "contributor version". A contributor's "essential patent claims" are all patent claims owned or controlled by the contributor, whether already acquired or hereafter acquired, that would be infringed by some manner, permitted by this License, of making, using, or selling its contributor version, but do not include claims that would be infringed only as a consequence of further modification of the contributor version. For purposes of this definition, "control" includes the right to grant patent sublicenses in a manner consistent with the requirements of this License. Each contributor grants you a non-exclusive, worldwide, royalty-free patent license under the contributor's essential patent claims, to make, use, sell, offer for sale, import and otherwise run, modify and propagate the contents of its contributor version. In the following three paragraphs, a "patent license" is any express agreement or commitment, however denominated, not to enforce a patent (such as an express permission to practice a patent or covenant not to sue for patent infringement). To "grant" such a patent license to a party means to make such an agreement or commitment not to enforce a patent against the party. If you convey a covered work, knowingly relying on a patent license, and the Corresponding Source of the work is not available for anyone to copy, free of charge and under the terms of this License, through a publicly available network server or other readily accessible means, then you must either (1) cause the Corresponding Source to be so available, or (2) arrange to deprive yourself of the benefit of the patent license for this particular work, or (3) arrange, in a manner consistent with the requirements of this License, to extend the patent license to downstream recipients. "Knowingly relying" means you have actual knowledge that, but for the patent license, your conveying the covered work in a country, or your recipient's use of the covered work in a country, would infringe one or more identifiable patents in that country that you have reason to believe are valid. If, pursuant to or in connection with a single transaction or arrangement, you convey, or propagate by procuring conveyance of, a covered work, and grant a patent license to some of the parties receiving the covered work authorizing them to use, propagate, modify or convey a specific copy of the covered work, then the patent license you grant is automatically extended to all recipients of the covered work and works based on it. A patent license is "discriminatory" if it does not include within the scope of its coverage, prohibits the exercise of, or is conditioned on the non-exercise of one or more of the rights that are specifically granted under this License. You may not convey a covered work if you are a party to an arrangement with a third party that is in the business of distributing software, under which you make payment to the third party based on the extent of your activity of conveying the work, and under which the third party grants, to any of the parties who would receive the covered work from you, a discriminatory patent license (a) in connection with copies of the covered work conveyed by you (or copies made from those copies), or (b) primarily for and in connection with specific products or compilations that contain the covered work, unless you entered into that arrangement, or that patent license was granted, prior to 28 March 2007. Nothing in this License shall be construed as excluding or limiting any implied license or other defenses to infringement that may otherwise be available to you under applicable patent law. 12. No Surrender of Others' Freedom. If 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 convey a covered work so as to satisfy simultaneously your obligations under this License and any other pertinent obligations, then as a consequence you may not convey it at all. For example, if you agree to terms that obligate you to collect a royalty for further conveying from those to whom you convey the Program, the only way you could satisfy both those terms and this License would be to refrain entirely from conveying the Program. 13. Use with the GNU Affero General Public License. Notwithstanding any other provision of this License, you have permission to link or combine any covered work with a work licensed under version 3 of the GNU Affero General Public License into a single combined work, and to convey the resulting work. The terms of this License will continue to apply to the part which is the covered work, but the special requirements of the GNU Affero General Public License, section 13, concerning interaction through a network will apply to the combination as such. 14. Revised Versions of this License. The Free Software Foundation may publish revised and/or new versions of the GNU 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 Program specifies that a certain numbered version of the GNU General Public License "or any later version" applies to it, you have the option of following the terms and conditions either of that numbered version or of any later version published by the Free Software Foundation. If the Program does not specify a version number of the GNU General Public License, you may choose any version ever published by the Free Software Foundation. If the Program specifies that a proxy can decide which future versions of the GNU General Public License can be used, that proxy's public statement of acceptance of a version permanently authorizes you to choose that version for the Program. Later license versions may give you additional or different permissions. However, no additional obligations are imposed on any author or copyright holder as a result of your choosing to follow a later version. 15. Disclaimer of Warranty. THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "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 PROGRAM IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. 16. Limitation of Liability. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS THE PROGRAM 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 PROGRAM (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 PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. 17. Interpretation of Sections 15 and 16. If the disclaimer of warranty and limitation of liability provided above cannot be given local legal effect according to their terms, reviewing courts shall apply local law that most closely approximates an absolute waiver of all civil liability in connection with the Program, unless a warranty or assumption of liability accompanies a copy of the Program in return for a fee. END OF TERMS AND CONDITIONS How to Apply These Terms to Your New Programs If you develop a new program, and you want it to be of the greatest possible use to the public, the best way to achieve this is to make it free software which everyone can redistribute and change under these terms. To do so, attach the following notices to the program. It is safest to attach them to the start of each source file to most effectively state 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 program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program 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 General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see . Also add information on how to contact you by electronic and paper mail. If the program does terminal interaction, make it output a short notice like this when it starts in an interactive mode: Copyright (C) This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'. This is free software, and you are welcome to redistribute it under certain conditions; type `show c' for details. The hypothetical commands `show w' and `show c' should show the appropriate parts of the General Public License. Of course, your program's commands might be different; for a GUI interface, you would use an "about box". You should also get your employer (if you work as a programmer) or school, if any, to sign a "copyright disclaimer" for the program, if necessary. For more information on this, and how to apply and follow the GNU GPL, see . The GNU General Public License does not permit incorporating your program into proprietary programs. If your program is a subroutine library, you may consider it more useful to permit linking proprietary applications with the library. If this is what you want to do, use the GNU Lesser General Public License instead of this License. But first, please read . ipe-7.1.4/install.txt0000644000175000017500000002647112120621776014377 0ustar otfriedotfried-------------------------------------------------------------------- Building and installing Ipe on Unix -------------------------------------------------------------------- Quickstart for Linux -------------------- If you have a recent Mint, Ubuntu, or Debian system, the following steps will install the necessary libraries and tools: sudo apt-get install checkinstall zlib1g-dev libqt4-dev sudo apt-get install libfreetype6-dev libcairo2-dev sudo apt-get install liblua5.2-dev gsfonts On Fedora, use the following steps instead: sudo yum -y install zlib-devel qt-devel freetype-devel cairo-devel sudo yum -y install lua-devel ghostscript-fonts urw-fonts Now you can compile and install Ipe into /usr/local: (Note that 7.x.y has to be replaced by the current Ipe version!) cd src make IPEPREFIX=/usr/local IPE_USE_ICONV=-DIPE_USE_ICONV sudo checkinstall --pkgname=ipe --pkgversion=7.x.y --backup=no \ --fstrans=no --default make install IPEPREFIX=/usr/local sudo cp ../fontmaps/gsfonts-fontmap.xml \ /usr/local/share/ipe/7.x.y/fontmap.xml sudo ldconfig The line with "checkinstall" makes sure that Ipe is installed as package "ipe". If you no longer need Ipe, or to remove it before compiling the next release, you can completely remove it from your system by saying sudo rm /usr/local/share/ipe/7.x.y/fontmap.xml sudo apt-get remove ipe Quickstart for MacOS 10.6 and 10.7 ---------------------------------- If you have macports, you can compile and install Ipe by simply saying sudo port install ipe This will take a long time (run it over night!), and may not compile the latest version if the macports recipe has not yet been updated. With a little manual work, you can compile Ipe without using macports, as follows: * Install Qt Run the binary installer for the Qt SDK for Mac from "qt.nokia.com/downloads". Ipe only needs the Qt libraries, so to save time and storage you could install the "Qt libraries for Mac" only. Either 4.7.3 or 4.6.4 (Cocoa) will work, or presumably any later version. * Install Lua Download the prebuild binaries from http://luabinaries.sourceforge.net/download.html You need the "lua-5.2.1_MacOS107_lib.tar.gz" package only. Copy the header files ("lua.h" and other ".h" files) into "/usr/local/include". Copy "liblua52.dylib" into "/usr/local/lib". DO NOT install "liblua52.a" on your system. * Now you can either manually compile and install Ipe, or you can build a MacOS application bundle (which you can then install on several machines). (1) Simple compile and install: cd src make IPEPREFIX=/usr/local sudo make install IPEPREFIX=/usr/local sudo cp ../fontmaps/mactex2011-fontmap.xml \ /usr/local/share/ipe/7.x.y/fontmap.xml (where 7.x.y has to be replaced by the current Ipe version) (2) To build an application bundle, just run the script "mac_make_bundle.sh". (The last line of the script contains the Ipe version number - make sure it's set properly!) cd src bash mac_make_bundle.sh The bundle will contain Qt and Lua, so you do not need to install those manually to install Ipe on another Mac. If something doesn't work for you, please read below to check the details! -------------------------------------------------------------------- Supported platforms ------------------- Ipe should compile on most Unix platforms and on Microsoft Windows. Mac OS X is not an officially supported platform - while it is based on a Unix kernel, the Apple application infrastructure is proprietary and quite different from standard Unix. I do not own an Apple computer, and cannot help you with building or installing Ipe on Mac OS. -------------------------------------------------------------------- Required components ------------------- Before you can compile Ipe, you will need to have the following tools and libraries: * GNU make The Ipe makefiles are written for GNU make. A Linux system will already have it. On other Unix systems, GNU make is often installed as 'gmake'. Otherwise, install it yourself from www.gnu.org. Other "make" implementations will not work! MacOS 10.6 already has this. * The compression library 'zlib' Very likely you already have it on your system (check for the include file "zlib.h"). If not, obtain it from "www.gzip.org/zlib" and install it. MacOS 10.6 already has this. * The font library 'Freetype 2' On Linux, you most likely already have this on your system. You will need the development package (on Debian/Ubuntu, this is "libfreetype6-dev"). MacOS 10.6 already has this. The original sources are at "www.freetype.org". You need version 2.1.8 or newer. * The Cairo library (version 1.8.0 or higher) The Gnome desktop uses this high-quality rendering library, so you may already have it. You will need the development package, e.g. on Debian/Ubuntu "libcairo2-dev". MacOS 10.6 already has this. You can also install from sources at "www.cairographics.org". If you compile Cairo yourself, note that you only need the image and svg surfaces (backends). You also need freetype support, but no fontconfig. Since Ipe does not need any platform-dependent backends, Cairo should compile fine on any platform. * The Lua language (version 5.2) Lua is an embeddable scripting language. On Debian/Ubuntu, install "liblua5.2-dev". Or compile from source at "www.lua.org" - the sources are ANSI C and compile very easily. Ipe requires Lua 5.2, and will not work with Lua 5.1. Make sure that you build a DYNAMIC library. Ipe will not work if Lua is linked statically (linking statically would include three copies of the Lua interpreter, resulting in random crashes). On Mac OS 10.6, you can use the prebuild binaries from http://luabinaries.sourceforge.net/download.html See the Quickstart above for installation. If you compile Lua yourself, note that "make macosx" compiles a static library - but you really MUST compile a shared library, so you need to modify the Makefile. * The Qt toolkit (version 4.5 or higher) On Linux, you most likely already have it. On Debian/Ubuntu, you would need the package "libqt4-dev". On MacOS 10.6, run the binary installer from "qt.nokia.com/downloads" (see Quickstart instructions above). You can also find the sources at "qt.digia.com". You only need the QtCore and QtGui libraries. * The 14 standard Postscript fonts If you create text objects using the 14 standard Postscript fonts (Times, Helvetica, Courier) the font doesn't need to be embedded in the PDF file. Still, Ipe needs access to the font to display it on the screen, and that's why you need to provide these 14 font files. The path of least resistance would be to download the fonts as "urw-fonts.zip" from the same place where you got Ipe. Use the supplied file "urw-fontmap.xml" as the fontmap for these fonts (see below for installation of the fontmap). However, very likely you have these fonts already on your system, for instance in "/usr/share/fonts/type1/gsfonts/" under the names: n019003l.pfb n019004l.pfb n019023l.pfb n019024l.pfb n021003l.pfb n021004l.pfb n021023l.pfb n021024l.pfb n022003l.pfb n022004l.pfb n022023l.pfb n022024l.pfb s050000l.pfb d050000l.pfb Identical fonts may also be in subdirectories of "/usr/share/texmf/fonts/type1/urw" or "/usr/share/texmf-texlive/fonts/type1/urw", under the names ucrb8a.pfb ucrbo8a.pfb ucrr8a.pfb ucrro8a.pfb uhvb8a.pfb uhvbo8a.pfb uhvr8a.pfb uhvro8a.pfb usyr.pfb utmb8a.pfb utmbi8a.pfb utmr8a.pfb utmri8a.pfb uzdr.pfb Your system may have a fontmap file describing all the fonts on the system in XML-format, similar to the supplied files "gsfonts-fontmap.xml" and "texlive-fontmap.xml". If so, Ipe can directly read this file and find the fonts, and all you need to do is to provide the path to the fontmap. If not, one of the supplied fontmaps may already be correct. On Debian/Ubuntu, "gsfonts-fontmap.xml" should be correct if you have the "gsfonts" package installed. On Mac OS X with MacTeX-2011, you can use "mactex2011-fontmap.xml". (You may have to update the year in the file.) Otherwise you can check for the location of the necessary files, and create your own fontmap. If you use relative paths in the fontmap, they are interpreted relative to the directory containing the fontmap file. * Pdflatex Ipe uses Pdflatex, a PDF-producing version of Latex, to convert Latex source code to Postscript/PDF. Every modern TeX installation includes it. Ipe likes Pdftex 1.40. If you have an earlier version of Pdftex, set the environment variable IPEANCIENTPDFTEX when running Ipe. Configuring and building Ipe ---------------------------- There are some pieces of information you need to provide to the Ipe build process by editing "src/config.mak" (in many cases you can also just give the definitions on the make command line, see below). You first have to indicate the location of the required components listed above. On Linux, you probably have a correctly working 'pkg-config' script, and the default settings should work. You'll have to check that the Lua package name is correct - try saying pkg-config --modversion lua5.2 If the package isn't found, try 'lua' or 'lua52'. Second, you have to define the Ipe directory structure. Normally, you would only need to define IPEPREFIX properly, depending on where you want Ipe to be installed. Indicate in IPEFONTMAP the path for "fontmap.xml" (if you are using a system fontmap, indicate the correct path; if you are using/making one specifically for Ipe place the fontmap in this location). These steps will then build Ipe: cd src make make install Instead of editing "src/config.mak", you can also set the variables in the make call, e.g.: cd src make IPEPREFIX=/usr IPEFONTMAP=/etc/ipe/fontmap.xml sudo make install IPEPREFIX=/usr You may need to do "make install" as root (depending on whether you have write permission to the installation location). Installing a fontmap -------------------- If you have made a "fontmap.xml" for Ipe, move it into the location you specified in "config.mak". In case you are using "urw-fonts.zip", move "urw-fontmap.xml" to "IPEPREFIX/share/ipe/IPEVERS/fontmap.xml", and unpack the 14 fonts from "urw-fonts.zip" into "IPEPREFIX/share/ipe/IPEVERS/fonts" (assuming you haven't changed the standard definition of IPEFONTMAP). Note that "make install" DOES NOT install any fontmap - you have to do this one step manually. Dynamic linking --------------- The Ipe libraries are shared libraries, and so your dynamic linker has to find "libipe*.so". If you have chosen a standard library directory for IPELIBDIR, saying "sudo ldconfig" will be enough to run Ipe. If you installed in a different location, such as "/opt/ipe7", you can make a small script called "ipe" like the following, and put it in your path: #!/bin/sh export LD_LIBRARY_PATH="/opt/ipe7/lib/:$LD_LIBRARY_PATH" /opt/ipe7/bin/ipe $* & Alternatively, you could put links to the library in a standard location: sudo ln -f -s IPELIBDIR/lib* /usr/lib sudo ldconfig -------------------------------------------------------------------- ipe-7.1.4/styles/0000755000175000017500000000000012120621776013501 5ustar otfriedotfriedipe-7.1.4/styles/beamer.isy0000644000175000017500000001145712120621776015472 0ustar otfriedotfried \makeatletter \renewcommand{\rmdefault}{cmss} \def\mathfamilydefault{\sfdefault} \SetSymbolFont{operators}{normal}{OT1}{cmss}{m}{n} \SetSymbolFont{operators}{bold}{OT1}{cmss}{bx}{n} \DeclareSymbolFont{numbers}{\encodingdefault}{\mathfamilydefault}{m}{n} \DeclareSymbolFont{pureletters}{\encodingdefault}{\mathfamilydefault}{m}{it} \SetMathAlphabet{\mathrm}{normal}{\encodingdefault}{\rmdefault}{m}{n} \DeclareMathAlphabet{\mathbf}{\encodingdefault}{\mathfamilydefault}{bx}{n} \DeclareMathAlphabet{\mathsf}{\encodingdefault}{\sfdefault}{m}{n} \DeclareMathAlphabet{\mathit}{\encodingdefault}{\mathfamilydefault}{m}{it} \DeclareMathAlphabet{\mathtt}{\encodingdefault}{\ttdefault}{m}{n} \SetSymbolFont{numbers}{bold}{\encodingdefault}{\mathfamilydefault}{bx}{n} \SetSymbolFont{pureletters}{bold}{\encodingdefault}{\mathfamilydefault}{bx}{it} \SetMathAlphabet{\mathrm}{bold}{\encodingdefault}{\rmdefault}{bx}{n} \SetMathAlphabet{\mathbf}{bold}{\encodingdefault}{\mathfamilydefault}{bx}{n} \SetMathAlphabet{\mathsf}{bold}{\encodingdefault}{\sfdefault}{bx}{n} \SetMathAlphabet{\mathit}{bold}{\encodingdefault}{\mathfamilydefault}{bx}{it} \SetMathAlphabet{\mathtt}{bold}{\encodingdefault}{\ttdefault}{bx}{n} \def\operator@font{\mathgroup\symnumbers} \DeclareMathSymbol{0}\mathalpha{numbers}{"30} \DeclareMathSymbol{1}\mathalpha{numbers}{"31} \DeclareMathSymbol{2}\mathalpha{numbers}{"32} \DeclareMathSymbol{3}\mathalpha{numbers}{"33} \DeclareMathSymbol{4}\mathalpha{numbers}{"34} \DeclareMathSymbol{5}\mathalpha{numbers}{"35} \DeclareMathSymbol{6}\mathalpha{numbers}{"36} \DeclareMathSymbol{7}\mathalpha{numbers}{"37} \DeclareMathSymbol{8}\mathalpha{numbers}{"38} \DeclareMathSymbol{9}\mathalpha{numbers}{"39} \DeclareMathSymbol{A}\mathalpha{pureletters}{"41} \DeclareMathSymbol{B}\mathalpha{pureletters}{"42} \DeclareMathSymbol{C}\mathalpha{pureletters}{"43} \DeclareMathSymbol{D}\mathalpha{pureletters}{"44} \DeclareMathSymbol{E}\mathalpha{pureletters}{"45} \DeclareMathSymbol{F}\mathalpha{pureletters}{"46} \DeclareMathSymbol{G}\mathalpha{pureletters}{"47} \DeclareMathSymbol{H}\mathalpha{pureletters}{"48} \DeclareMathSymbol{I}\mathalpha{pureletters}{"49} \DeclareMathSymbol{J}\mathalpha{pureletters}{"4A} \DeclareMathSymbol{K}\mathalpha{pureletters}{"4B} \DeclareMathSymbol{L}\mathalpha{pureletters}{"4C} \DeclareMathSymbol{M}\mathalpha{pureletters}{"4D} \DeclareMathSymbol{N}\mathalpha{pureletters}{"4E} \DeclareMathSymbol{O}\mathalpha{pureletters}{"4F} \DeclareMathSymbol{P}\mathalpha{pureletters}{"50} \DeclareMathSymbol{Q}\mathalpha{pureletters}{"51} \DeclareMathSymbol{R}\mathalpha{pureletters}{"52} \DeclareMathSymbol{S}\mathalpha{pureletters}{"53} \DeclareMathSymbol{T}\mathalpha{pureletters}{"54} \DeclareMathSymbol{U}\mathalpha{pureletters}{"55} \DeclareMathSymbol{V}\mathalpha{pureletters}{"56} \DeclareMathSymbol{W}\mathalpha{pureletters}{"57} \DeclareMathSymbol{X}\mathalpha{pureletters}{"58} \DeclareMathSymbol{Y}\mathalpha{pureletters}{"59} \DeclareMathSymbol{Z}\mathalpha{pureletters}{"5A} \DeclareMathSymbol{a}\mathalpha{pureletters}{"61} \DeclareMathSymbol{b}\mathalpha{pureletters}{"62} \DeclareMathSymbol{c}\mathalpha{pureletters}{"63} \DeclareMathSymbol{d}\mathalpha{pureletters}{"64} \DeclareMathSymbol{e}\mathalpha{pureletters}{"65} \DeclareMathSymbol{f}\mathalpha{pureletters}{"66} \DeclareMathSymbol{g}\mathalpha{pureletters}{"67} \DeclareMathSymbol{h}\mathalpha{pureletters}{"68} \DeclareMathSymbol{i}\mathalpha{pureletters}{"69} \DeclareMathSymbol{j}\mathalpha{pureletters}{"6A} \DeclareMathSymbol{k}\mathalpha{pureletters}{"6B} \DeclareMathSymbol{l}\mathalpha{pureletters}{"6C} \DeclareMathSymbol{m}\mathalpha{pureletters}{"6D} \DeclareMathSymbol{n}\mathalpha{pureletters}{"6E} \DeclareMathSymbol{o}\mathalpha{pureletters}{"6F} \DeclareMathSymbol{p}\mathalpha{pureletters}{"70} \DeclareMathSymbol{q}\mathalpha{pureletters}{"71} \DeclareMathSymbol{r}\mathalpha{pureletters}{"72} \DeclareMathSymbol{s}\mathalpha{pureletters}{"73} \DeclareMathSymbol{t}\mathalpha{pureletters}{"74} \DeclareMathSymbol{u}\mathalpha{pureletters}{"75} \DeclareMathSymbol{v}\mathalpha{pureletters}{"76} \DeclareMathSymbol{w}\mathalpha{pureletters}{"77} \DeclareMathSymbol{x}\mathalpha{pureletters}{"78} \DeclareMathSymbol{y}\mathalpha{pureletters}{"79} \DeclareMathSymbol{z}\mathalpha{pureletters}{"7A} \DeclareOldFontCommand{\rm}{\normalfont\rmfamily}{\mathrm} \DeclareOldFontCommand{\sf}{\normalfont\sffamily}{\mathsf} \DeclareOldFontCommand{\tt}{\normalfont\ttfamily}{\mathtt} \DeclareOldFontCommand{\bf}{\normalfont\bfseries}{\mathbf} \DeclareOldFontCommand{\it}{\normalfont\itshape}{\mathit} \DeclareOldFontCommand{\sl}{\normalfont\slshape}{\@nomath\sl} \DeclareOldFontCommand{\sc}{\normalfont\scshape}{\@nomath\sc} \DeclareRobustCommand*\cal{\@fontswitch\relax\mathcal} \DeclareRobustCommand*\mit{\@fontswitch\relax\mathnormal} \makeatother ipe-7.1.4/styles/transparency.isy0000644000175000017500000000021012120621776016731 0ustar otfriedotfried ipe-7.1.4/styles/basic.isy0000644000175000017500000001300212120621776015304 0ustar otfriedotfried 0.6 0 0 0.6 0 0 e 0.4 0 0 0.4 0 0 e 0.6 0 0 0.6 0 0 e 0.5 0 0 0.5 0 0 e 0.6 0 0 0.6 0 0 e 0.4 0 0 0.4 0 0 e -0.6 -0.6 m 0.6 -0.6 l 0.6 0.6 l -0.6 0.6 l h -0.4 -0.4 m 0.4 -0.4 l 0.4 0.4 l -0.4 0.4 l h -0.6 -0.6 m 0.6 -0.6 l 0.6 0.6 l -0.6 0.6 l h -0.5 -0.5 m 0.5 -0.5 l 0.5 0.5 l -0.5 0.5 l h -0.6 -0.6 m 0.6 -0.6 l 0.6 0.6 l -0.6 0.6 l h -0.4 -0.4 m 0.4 -0.4 l 0.4 0.4 l -0.4 0.4 l h -0.43 -0.57 m 0.57 0.43 l 0.43 0.57 l -0.57 -0.43 l h -0.43 0.57 m 0.57 -0.43 l 0.43 -0.57 l -0.57 0.43 l h 0 0 m -1.0 0.333 l -1.0 -0.333 l h 0 0 m -1.0 0.333 l -1.0 -0.333 l h 0 0 m -1.0 0.333 l -1.0 -0.333 l h 0 0 m -1.0 0.333 l -0.8 0 l -1.0 -0.333 l h 0 0 m -1.0 0.333 l -0.8 0 l -1.0 -0.333 l h -1.0 0.333 m 0 0 l -1.0 -0.333 l 0 0 m -1.0 0.333 l -1.0 -0.333 l h -1 0 m -2.0 0.333 l -2.0 -0.333 l h 0 0 m -1.0 0.333 l -1.0 -0.333 l h -1 0 m -2.0 0.333 l -2.0 -0.333 l h ipe-7.1.4/styles/presentation.isy0000644000175000017500000001520212120621776016742 0ustar otfriedotfried 0.6 0 0 0.6 0 0 e 0.4 0 0 0.4 0 0 e 0.6 0 0 0.6 0 0 e 0.5 0 0 0.5 0 0 e 0.6 0 0 0.6 0 0 e 0.4 0 0 0.4 0 0 e -0.6 -0.6 m 0.6 -0.6 l 0.6 0.6 l -0.6 0.6 l h -0.4 -0.4 m 0.4 -0.4 l 0.4 0.4 l -0.4 0.4 l h -0.6 -0.6 m 0.6 -0.6 l 0.6 0.6 l -0.6 0.6 l h -0.5 -0.5 m 0.5 -0.5 l 0.5 0.5 l -0.5 0.5 l h -0.6 -0.6 m 0.6 -0.6 l 0.6 0.6 l -0.6 0.6 l h -0.4 -0.4 m 0.4 -0.4 l 0.4 0.4 l -0.4 0.4 l h -0.43 -0.57 m 0.57 0.43 l 0.43 0.57 l -0.57 -0.43 l h -0.43 0.57 m 0.57 -0.43 l 0.43 -0.57 l -0.57 0.43 l h 0 0 m -1.0 0.333 l -1.0 -0.333 l h 0 0 m -1.0 0.333 l -1.0 -0.333 l h 0 0 m -1.0 0.333 l -1.0 -0.333 l h 0 0 m -1.0 0.333 l -0.8 0 l -1.0 -0.333 l h 0 0 m -1.0 0.333 l -0.8 0 l -1.0 -0.333 l h -1.0 0.333 m 0 0 l -1.0 -0.333 l 0 0 m -1.0 0.333 l -1.0 -0.333 l h -1 0 m -2.0 0.333 l -2.0 -0.333 l h 0 0 m -1.0 0.333 l -1.0 -0.333 l h -1 0 m -2.0 0.333 l -2.0 -0.333 l h \renewcommand\rmdefault{cmss} \makeatletter \leftmargini 1.5em \leftmargin \leftmargini \leftmarginii 1.2em \leftmarginiii 1em \def\@listI{\leftmargin\leftmargini \parsep \z@ \partopsep 3pt \topsep \z@ \itemsep \z@} \@listI \def\@listii {\leftmargin\leftmarginii \labelwidth\leftmarginii \advance\labelwidth-\labelsep \topsep \z@ \parsep \z@ \itemsep \parsep} \def\@listiii{\leftmargin\leftmarginiii \labelwidth\leftmarginiii \advance\labelwidth-\labelsep \topsep \z@ \parsep \z@ \partopsep \z@ \itemsep \topsep} \makeatother ipe-7.1.4/styles/colors.isy0000644000175000017500000007734612120621776015551 0ustar otfriedotfried ipe-7.1.4/windows-compilation.txt0000644000175000017500000000340712120621776016731 0ustar otfriedotfried Compiling Ipe under Windows (contributed by Daniel Beckmann) You need the following tools and libraries to compile ipe: - MinGW. From www.mingw.org, install base package into C:/MinGW/. Qt requires g++ 4.4, and will not work with the default 4.7 that you will get if you install g++ from the MinGW install tool, so you need to download 'gcc-full-4.4.0-mingw32-bin-2.tar.lzma' and unpack it into C:/MinGW as well. Open a MinGW Shell and say "g++ --version" to check that you have g++ 4.4 available. - QT. From qt-project.org/downloads, install qt-win-opensource-4.8.4-mingw into E:/Qt/4.8.4/ (or edit "common.mak" later) (The Qt installation will complain if your Win32 API is not equal to 3.13. It seems that ignoring this and using the Win32 API 3.17 that comes with MinGW works fine.) - Cairo, Freetype2, zlib, etc. Precompiled binaries can be found at http://ftp.gnome.org/pub/gnome/binaries/win32/dependencies/ I used: cairo_1.10.2-2_win32.zip cairo-dev_1.10.2-2_win32.zip freetype_2.4.4-1_win32.zip freetype-dev_2.4.4-1_win32.zip zlib_1.2.5-2_win32.zip zlib-dev_1.2.5-2_win32.zip fontconfig_2.8.0-2_win32.zip expat_2.1.0-1_win32.zip libpng_1.4.12-1_win32.zip Extract all into E:/IpeDeps (or edit "common.mak" later) - Lua language Precompiled binaries can be found at http://sourceforge.net/projects/luabinaries/ I used: lua-5.2.1_Win32_dllw4_lib.zip extracted in E:/IpeDeps/lua52 If you have used directories different from E:/Qt/4.8.4/ and E:/IpeDeps, edit "common.mak" and change the setting of QTHOME and IPEDEPS in the "Compiling with MinGW32 under Windows" section. Open MinGWShell, navigate into ipe-7.x.x/src folder and say "make" All files should be compiled in ipe-7.x.x/mingw/bin folder ipe-7.1.4/man/0000755000175000017500000000000012120621776012731 5ustar otfriedotfriedipe-7.1.4/man/ipe6upgrade.10000644000175000017500000000322312120621776015226 0ustar otfriedotfried.\" Hey, EMACS: -*- nroff -*- .\" First parameter, NAME, should be all caps .\" Second parameter, SECTION, should be 1-8, maybe w/ subsection .\" other parameters are allowed: see man(7), man(1) .\" TeX users may be more comfortable with the \fB\fP and .\" \fI\fP escape sequences to invode bold face and italics, .\" respectively. .TH IPE6UPGRADE 1 "September 29, 2009" .\" Please adjust this date whenever revising the manpage. .\" .\" Some roff macros, for reference: .\" .nh disable hyphenation .\" .hy enable hyphenation .\" .ad l left justify .\" .ad b justify to both left and right margins .\" .nf disable filling .\" .fi enable filling .\" .br insert line break .\" .sp insert n+1 empty lines .\" for manpage-specific macros, see man(7) .SH NAME ipe6upgrade \- Convert Ipe 6 file format to Ipe 7 file format .SH SYNOPSIS .B ipe6upgrade \fIinput-file\fP [ \fIoutput-file\fP ] .SH DESCRIPTION .PP \fBipe6upgrade\fP converts an XML file in any version of the Ipe 6 file format to Ipe 7 format. If the \fIoutput-file\fP is not given, \fBipe6upgrade\fP replaces the input file extension by \fIipe\fP. .SH ENVIRONMENT VARIABLES \fBipe6upgrade\fP respects the following environment variables: .TP \fBIPEDEBUG\fP set this to 1 for debugging output from \fBipe6upgrade\fP. .SH AUTHOR Otfried Cheong .SH REPORTING BUGS .ad l Please report bugs using Ipe bugzilla at .I "http://ipe7.sourceforge.net/bugzilla.html" .SH SEE ALSO .ad l Ipe is documented fully in .IR "The Ipe Manual" , which is available online at .I "http://ipe7.sourceforge.net/manual/manual.html" . ipe-7.1.4/man/ipescript.10000644000175000017500000000417212120621776015021 0ustar otfriedotfried.\" Hey, EMACS: -*- nroff -*- .\" First parameter, NAME, should be all caps .\" Second parameter, SECTION, should be 1-8, maybe w/ subsection .\" other parameters are allowed: see man(7), man(1) .\" TeX users may be more comfortable with the \fB\fP and .\" \fI\fP escape sequences to invode bold face and italics, .\" respectively. .TH IPESCRIPT 1 "August 28, 2011" .\" Please adjust this date whenever revising the manpage. .\" .\" Some roff macros, for reference: .\" .nh disable hyphenation .\" .hy enable hyphenation .\" .ad l left justify .\" .ad b justify to both left and right margins .\" .nf disable filling .\" .fi enable filling .\" .br insert line break .\" .sp insert n+1 empty lines .\" for manpage-specific macros, see man(7) .SH NAME ipescript \- Run an Ipe script (written in Lua) .SH SYNOPSIS .B ipescript \fIscript\fP { \fIarguments\fP } .SH DESCRIPTION .PP \fBipescript\fP runs an Ipe script written in Lua. The Ipe bindings are automatically available in the script. Ipescript looks for the script in any of the script directories. .PP The \fIscript\fP argument should not contain the .lua extension. .SH ENVIRONMENT VARIABLES \fBipescript\fP respects the following environment variables: .TP \fBIPELATEXDIR\fP the directory where \fBipetoipe\fP runs Pdflatex. .TP \fBIPESCRIPTS\fP a list of directories where Ipescript will look for scripts. When this variable is not set, Ipe searches first the current directory, then \fI~/.ipe/scripts\fP, and finally the system-wide Ipe script directory. When this variable is set, it should contain a list of directories, separated by semicolons. A single underscore is replaced by the system-wide Ipe script directory. .TP \fBIPEDEBUG\fP set this to 1 for debugging output from \fBipescript\fP. .SH AUTHOR Otfried Cheong .SH REPORTING BUGS .ad l Please report bugs using Ipe bugzilla at .I "http://ipe7.sourceforge.net/bugzilla.html" .SH SEE ALSO .ad l Ipe is documented fully in .IR "The Ipe Manual" , which is available online at .I "http://ipe7.sourceforge.net/manual/manual.html" . ipe-7.1.4/man/ipeextract.10000644000175000017500000000326412120621776015170 0ustar otfriedotfried.\" Hey, EMACS: -*- nroff -*- .\" First parameter, NAME, should be all caps .\" Second parameter, SECTION, should be 1-8, maybe w/ subsection .\" other parameters are allowed: see man(7), man(1) .\" TeX users may be more comfortable with the \fB\fP and .\" \fI\fP escape sequences to invode bold face and italics, .\" respectively. .TH IPEEXTRACT 1 "June 27, 2009" .\" Please adjust this date whenever revising the manpage. .\" .\" Some roff macros, for reference: .\" .nh disable hyphenation .\" .hy enable hyphenation .\" .ad l left justify .\" .ad b justify to both left and right margins .\" .nf disable filling .\" .fi enable filling .\" .br insert line break .\" .sp insert n+1 empty lines .\" for manpage-specific macros, see man(7) .SH NAME ipeextract \- Extract Ipe XML stream from Ipe PDF or EPS files .SH SYNOPSIS .B ipeextract \fIinput-file\fP [ \fIoutput-file\fP ] .SH DESCRIPTION .PP \fBipeextract\fP extracts the Ipe XML stream from an Ipe document in PDF or Postscript format generated by any version of Ipe 6 or Ipe 7. If the \fIoutput-file\fP is not given, \fBipeextract\fP replaces the input file extension by \fIxml\fP. .SH ENVIRONMENT VARIABLES \fBipeextract\fP respects the following environment variables: .TP \fBIPEDEBUG\fP set this to 1 for debugging output from \fBipeextract\fP. .SH AUTHOR Otfried Cheong .SH REPORTING BUGS .ad l Please report bugs using Ipe bugzilla at .I "http://ipe7.sourceforge.net/bugzilla.html" .SH SEE ALSO .ad l Ipe is documented fully in .IR "The Ipe Manual" , which is available online at .I "http://ipe7.sourceforge.net/manual/manual.html" . ipe-7.1.4/man/ipetoipe.10000644000175000017500000000564612120621776014644 0ustar otfriedotfried.\" Hey, EMACS: -*- nroff -*- .\" First parameter, NAME, should be all caps .\" Second parameter, SECTION, should be 1-8, maybe w/ subsection .\" other parameters are allowed: see man(7), man(1) .\" TeX users may be more comfortable with the \fB\fP and .\" \fI\fP escape sequences to invode bold face and italics, .\" respectively. .TH IPETOIPE 1 "June 27, 2009" .\" Please adjust this date whenever revising the manpage. .\" .\" Some roff macros, for reference: .\" .nh disable hyphenation .\" .hy enable hyphenation .\" .ad l left justify .\" .ad b justify to both left and right margins .\" .nf disable filling .\" .fi enable filling .\" .br insert line break .\" .sp insert n+1 empty lines .\" for manpage-specific macros, see man(7) .SH NAME ipetoipe \- Convert between Ipe file formats .SH SYNOPSIS .B ipetoipe ( -pdf | -eps | -xml ) { options } \fIinput-file\fP [ \fIoutput-file\fP ] .SH DESCRIPTION .PP \fBipetoipe\fP converts between the three Ipe file formats XML, PDF, and EPS. Options are: .TP \fB-pdf\fP convert to PDF format .TP \fB-eps\fP convert to EPS (encapsulated Postscript) format .TP \fB-xml\fP convert to XML format .TP \fB-export\fP do not include Ipe markup in the output file. .br \fIWarning:\fP this means that Ipe will not be able to read the resulting output file. .TP \fB-pages\fP \fIfrom\fP-\fIto\fP restrict exporting to PDF to this page range. This implies the \fB-export\fP option. .TP \fB-view\fP \fIpage\fP-\fIview\fP only export this single view from the document. This implies the \fB-export\fP option. .TP \fB-markedview\fP create a Postscript/PDF page only for the marked views of marked Ipe pages. This is for instance convenient for making handouts for slides used in a presentation. This implies the \fB-export\fP option. .TP \fB-runlatex\fP run Latex even for XML output. This has the effect of including the dimensions of each text object in the XML file. .TP \fB-nocolor\fP do not use any color commands in Postscript output. This is useful if you are preparing a manuscript for publication where the publisher checks that the figures are grayscale only. Note that this option doesn't actually verify that the figure contains no color (a figure using color processed with this option will cause a Postscript error when displayed). .TP \fB-nozip\fP do not compress streams in PDF or Postscript output. .SH ENVIRONMENT VARIABLES \fBipetoipe\fP respects the following environment variables: .TP \fBIPELATEXDIR\fP the directory where \fBipetoipe\fP runs Pdflatex. .TP \fBIPEDEBUG\fP set this to 1 for debugging output. .SH AUTHOR Otfried Cheong .SH REPORTING BUGS .ad l Please report bugs using Ipe bugzilla at .I "http://ipe7.sourceforge.net/bugzilla.html" .SH SEE ALSO .ad l Ipe is documented fully in .IR "The Ipe Manual" , which is available online at .I "http://ipe7.sourceforge.net/manual/manual.html" . ipe-7.1.4/man/iperender.10000644000175000017500000000422012120621776014766 0ustar otfriedotfried.\" Hey, EMACS: -*- nroff -*- .\" First parameter, NAME, should be all caps .\" Second parameter, SECTION, should be 1-8, maybe w/ subsection .\" other parameters are allowed: see man(7), man(1) .\" TeX users may be more comfortable with the \fB\fP and .\" \fI\fP escape sequences to invode bold face and italics, .\" respectively. .TH IPERENDER 1 "June 27, 2009" .\" Please adjust this date whenever revising the manpage. .\" .\" Some roff macros, for reference: .\" .nh disable hyphenation .\" .hy enable hyphenation .\" .ad l left justify .\" .ad b justify to both left and right margins .\" .nf disable filling .\" .fi enable filling .\" .br insert line break .\" .sp insert n+1 empty lines .\" for manpage-specific macros, see man(7) .SH NAME iperender \- Export Ipe document as bitmap or SVG .SH SYNOPSIS .B iperender ( -svg | -png ) [ -page \fIpage\fP ] [ -view \fIview\fP ] [ -resolution \fIdpi\fP ] [ -transparent ] \fIinput-file\fP \fIoutput-file\fP .SH DESCRIPTION .PP \fBiperender\fP exports an Ipe document as a PNG bitmap or in SVG format. Options are: .TP \fB-png\fP convert to PNG format .TP \fB-svg\fP convert to SVG format .TP \fB-page\fP \fIpage\fP export this page from a multipage document. .TP \fB-view\fP \fIview\fP export this view from a page with multiple views. .TP \fB-resolution\fP \fIdpi\fP set resolution for exporting to PNG. .TP \fB-transparent\fP make background transparent when exporting to PNG. .SH ENVIRONMENT VARIABLES \fBipetoipe\fP respects the following environment variables: .TP \fBIPELATEXDIR\fP the directory where \fBipetoipe\fP runs Pdflatex. .TP \fBIPEFONTMAP\fP the complete path of the font map, describing where Ipe can find the 14 standard PDF fonts. .TP \fBIPEDEBUG\fP set this to 1 for debugging output from \fBiperender\fP. .SH AUTHOR Otfried Cheong .SH REPORTING BUGS .ad l Please report bugs using Ipe bugzilla at .I "http://ipe7.sourceforge.net/bugzilla.html" .SH SEE ALSO .ad l Ipe is documented fully in .IR "The Ipe Manual" , which is available online at .I "http://ipe7.sourceforge.net/manual/manual.html" . ipe-7.1.4/man/ipe.10000644000175000017500000000606212120621776013574 0ustar otfriedotfried.\" Hey, EMACS: -*- nroff -*- .\" First parameter, NAME, should be all caps .\" Second parameter, SECTION, should be 1-8, maybe w/ subsection .\" other parameters are allowed: see man(7), man(1) .\" TeX users may be more comfortable with the \fB\fP and .\" \fI\fP escape sequences to invoke bold face and italics, .\" respectively. .TH IPE 1 "September 1, 2011" .\" Please adjust this date whenever revising the manpage. .\" .\" Some roff macros, for reference: .\" .nh disable hyphenation .\" .hy enable hyphenation .\" .ad l left justify .\" .ad b justify to both left and right margins .\" .nf disable filling .\" .fi enable filling .\" .br insert line break .\" .sp insert n+1 empty lines .\" for manpage-specific macros, see man(7) .SH NAME ipe \- drawing editor for creating figures in PDF or EPS formats .SH SYNOPSIS .B ipe [ \fIQt options\fP ] [ -sheet \fIstylesheet\fP ] \fIfilename\fP .SH DESCRIPTION Ipe is a program that supports making small figures for inclusion into LaTeX documents as well as making multi-page PDF presentations. .PP This manual page only documents the command line options and environment variables. Full documentation for using Ipe can be found in HTML and PDF format; see below. .TP \fB\-sheet\fR \fIstylesheet\fP add the Ipe style sheet in the indicated file to all newly created Ipe documents. This option can be used more than once. .SH ENVIRONMENT VARIABLES Ipe respects the following environment variables: .TP \fBIPELATEXDIR\fP the directory where Ipe runs Pdflatex. .TP \fBIPEFONTMAP\fP the complete path of the font map, describing where Ipe can find the 14 standard PDF fonts. .TP \fBIPEANCIENTPDFTEX\fP set this variable to use Pdftex versions older than 1.40. .TP \fBIPELETPATH\fP a list of directories, separated by semicolons, containing ipelets. You can write a single underscore for the system-wide ipelet directory. If this variable is not set, the default consists of the system-wide ipelet directory, plus \fI~/.ipe/ipelets\fP on Unix, plus \fI~/Library/Ipe/Ipelets\fP on OS X. .TP \fBEDITOR\fP external editor to use for editing text objects. .TP \fBIPESTYLES\fP a list of directories, separated by semicolons, where Ipe looks for stylesheets. You can write a single underscore for the system-wide stylesheet directory. If this variable is not set, the default consists of the system-wide stylesheet directory, plus \fI~/.ipe/styles\fP on Unix, plus \fI~/Library/Ipe/Styles\fP on OS X. .TP \fBIPEDEBUG\fP set this to 1 for debugging output. .TP \fBIPEDOCDIR\fP the directory containing the Ipe documentation. .TP \fBIPEICONDIR\fP directory containing icons for the Ipe user interface. .TP \fBIPELUAPATH\fP path for searching for Ipe Lua code. .SH AUTHOR Otfried Cheong .SH REPORTING BUGS .ad l Please report bugs using Ipe bugzilla at .I "http://ipe7.sourceforge.net/bugzilla.html" .SH SEE ALSO .ad l Ipe is documented fully in .IR "The Ipe Manual" , which is available online at .I "http://ipe7.sourceforge.net/manual/manual.html" . ipe-7.1.4/src/0000755000175000017500000000000012120621776012745 5ustar otfriedotfriedipe-7.1.4/src/mac_make_bundle.sh0000644000175000017500000001330112120621776016365 0ustar otfriedotfried#! /bin/bash # Contributed by 'leahcimb', August 2011. ## Create directories for .app bundle APPDIR="$( cd "$( dirname "$0" )" && cd .. && pwd )"/Ipe.app APPFRAMEWORKS=$APPDIR/Contents/Frameworks APPMACOS=$APPDIR/Contents/MacOS APPPLUGINS=$APPDIR/Contents/PlugIns APPRESOURCES=$APPDIR/Contents/Resources APPLOCAL=$APPDIR/Contents/Resources/local mkdir -p $APPLOCAL/bin mkdir -p $APPLOCAL/lib mkdir -p $APPMACOS mkdir -p $APPFRAMEWORKS mkdir -p $APPPLUGINS ## Create config files for .app bundle. # Info.plist echo ' CFBundleDocumentTypes CFBundleTypeName Ipe figure CFBundleTypeIconFile ipe.icns LSHandlerRank Owner CFBundleTypeRole Editor CFBundleTypeExtensions ipe IPE CFBundleTypeName Postscript document CFBundleTypeIconFile ipe.icns LSHandlerRank Alternate CFBundleTypeRole Editor CFBundleTypeExtensions eps EPS CFBundleTypeName PDF document CFBundleTypeIconFile ipe.icns LSHandlerRank Alternate CFBundleTypeRole Editor CFBundleTypeExtensions pdf PDF CFBundleTypeMIMETypes application/pdf CFBundleDevelopmentRegion English CFBundleExecutable ipe CFBundleIconFile ipe.icns CFBundleIdentifier net.sourceforge.ipe7 CFBundleInfoDictionaryVersion 6.0 CFBundleName Ipe CFBundlePackageType APPL CFBundleShortVersionString @VERSION@ CFBundleSignature Ipe7 CFBundleVersion @VERSION@ NSHumanReadableCopyright Copyright (C) 1993-2013 Otfried Cheong ' > $APPDIR/Contents/Info.plist # ipe startup script echo '#! /bin/bash # IPELATEXDIR # IPEFONTMAP # IPEDEBUG # IPESTYLES # IPELETPATH # IPEICONDIR # IPEDOCDIR # IPELUAPATH # EDITOR DIR="$( cd "$( dirname "$0" )" && cd .. && pwd )"/Resources/local/bin PATH=$DIR:/usr/texbin:/usr/local/texbin:/usr/local/bin:$PATH (cd $DIR; ./ipe) ' > $APPDIR/Contents/MacOS/ipe chmod +x $APPDIR/Contents/MacOS/ipe # qt.conf echo '[Paths] Plugins = PlugIns ' > $APPDIR/Contents/Resources/qt.conf ln -s ../../../Resources/qt.conf $APPLOCAL/bin/qt.conf ## Copy Qt frameworks into .app bundle and set relative links cp -R /Library/Frameworks/QtCore.framework $APPFRAMEWORKS/ cp -R /Library/Frameworks/QtGui.framework $APPFRAMEWORKS/ cp -R /Library/Frameworks/QtNetwork.framework $APPFRAMEWORKS/ install_name_tool -id @executable_path/../../../Frameworks/QtCore.framework/Versions/4/QtCore $APPFRAMEWORKS/QtCore.framework/Versions/4/QtCore install_name_tool -id @executable_path/../../../Frameworks/QtGui.framework/Versions/4/QtGui $APPFRAMEWORKS/QtGui.framework/Versions/4/QtGui install_name_tool -id @executable_path/../../../Frameworks/QtNetwork.framework/Versions/4/QtNetwork $APPFRAMEWORKS/QtNetwork.framework/Versions/4/QtNetwork FIX_QTCORE='install_name_tool -change QtCore.framework/Versions/4/QtCore @executable_path/../../../Frameworks/QtCore.framework/Versions/4/QtCore' FIX_QTGUI='install_name_tool -change QtGui.framework/Versions/4/QtGui @executable_path/../../../Frameworks/QtGui.framework/Versions/4/QtGui' FIX_QTNETWORK='install_name_tool -change QtNetwork.framework/Versions/4/QtNetwork @executable_path/../../../Frameworks/QtNetwork.framework/Versions/4/QtNetwork' $FIX_QTCORE $APPFRAMEWORKS/QtGui.framework/Versions/4/QtGui $FIX_QTCORE $APPFRAMEWORKS/QtNetwork.framework/Versions/4/QtNetwork cp -R /Developer/Applications/Qt/plugins/accessible $APPPLUGINS/ cp -R /Developer/Applications/Qt/plugins/codecs $APPPLUGINS/ cp -R /Developer/Applications/Qt/plugins/graphicssystems $APPPLUGINS/ cp -R /Developer/Applications/Qt/plugins/imageformats $APPPLUGINS/ rm -rf $APPPLUGINS/accessible/libqtaccessiblecompatwidgets.dylib rm -rf $APPPLUGINS/graphicssystems/libqglgraphicssystem.dylib rm -rf $APPPLUGINS/imageformats/libqsvg.dylib ## Copy lua library cp /usr/local/lib/liblua52.dylib $APPLOCAL/lib/ install_name_tool -id @executable_path/../lib/liblua52.dylib $APPLOCAL/lib/liblua52.dylib ## Build ipe export INSTALL_ROOT=$APPDIR/Contents/Resources/1/2/ export LUA_LIBS="-L$APPDIR/Contents/Resources/local/lib -llua52 -lm" export IPEPREFIX=../../local export IPELIBDIRINFO=@executable_path/../lib make && make install rm -rf $APPRESOURCES/1 ## Fix dynamic library links find $APPLOCAL -d -type f -exec $FIX_QTCORE {} \; &> /dev/null find $APPLOCAL -d -type f -exec $FIX_QTGUI {} \; &> /dev/null find $APPLOCAL -d -type f -exec $FIX_QTNETWORK {} \; &> /dev/null find $APPPLUGINS -d -type f -exec $FIX_QTCORE {} \; &> /dev/null find $APPPLUGINS -d -type f -exec $FIX_QTGUI {} \; &> /dev/null find $APPPLUGINS -d -type f -exec $FIX_QTNETWORK {} \; &> /dev/null ## Create icon sips -s format icns $APPLOCAL/share/ipe/7.1.4/icons/ipe.png --out $APPRESOURCES/ipe.icns ipe-7.1.4/src/common.mak0000644000175000017500000001312612120621776014732 0ustar otfriedotfried# -*- makefile -*- # -------------------------------------------------------------------- # # Building Ipe --- common definitions # # -------------------------------------------------------------------- # Are we compiling for Windows? For Mac OS X? ifdef COMSPEC WIN32 = 1 else ifdef IPEMXE WIN32 = 1 else ifdef MINGWCROSS WIN32 = 1 else UNAME = $(shell uname) ifeq "$(UNAME)" "Darwin" MACOS = 1 endif endif # -------------------------------------------------------------------- # IPESRCDIR is Ipe's top "src" directory # if 'common.mak' is included on a different level than a subdirectory # of "src", then IPESRCDIR must be set before including 'common.mak'. IPESRCDIR ?= .. # -------------------------------------------------------------------- # Read configuration options (not used on Win32) ifndef WIN32 include $(IPESRCDIR)/config.mak endif # -------------------------------------------------------------------- ifdef WIN32 IPEUI ?= QT IPE_USE_ICONV := BUILDDIR = $(IPESRCDIR)/../mingw else BUILDDIR = $(IPESRCDIR)/../build endif # set variables for UI choice ifeq ($(IPEUI),QT) CPPFLAGS += -DIPEUI_QT IPEUI_QT := 1 UI_CFLAGS = $(QT_CFLAGS) UI_LIBS = $(QT_LIBS) moc_sources = $(addprefix moc_, $(subst .h,.cpp,$(moc_headers))) all_sources = $(sources) $(qt_sources) objects = $(addprefix $(OBJDIR)/, $(subst .cpp,.o,$(all_sources) \ $(moc_sources))) else ifeq ($(IPEUI), WIN32) CPPFLAGS += -DIPEUI_WIN32 IPEUI_WIN32 := 1 UI_CFLAGS := UI_LIBS := -lcomctl32 -lcomdlg32 -lgdi32 all_sources = $(sources) $(win_sources) objects = $(addprefix $(OBJDIR)/, $(subst .cpp,.o,$(all_sources))) else ifeq ($(IPEUI), GTK) CPPFLAGS += -DIPEUI_GTK IPEUI_GTK := 1 UI_CFLAGS = $(GTK_CFLAGS) UI_LIBS = $(GTK_LIBS) all_sources = $(sources) $(gtk_sources) BUILDDIR = $(IPESRCDIR)/../build-gtk objects = $(addprefix $(OBJDIR)/, $(subst .cpp,.o,$(all_sources))) else error("Unknown IPEUI selected") endif endif endif CXXFLAGS += -Wall ifdef IPESTRICT CXXFLAGS += -Werror endif DEPEND ?= $(OBJDIR)/depend.mak .PHONY: clean .PHONY: install .PHONY: all ifdef WIN32 CPPFLAGS += -DWIN32 DLL_LDFLAGS += -shared buildlib = $(BUILDDIR)/bin exe_target = $(BUILDDIR)/bin/$1.exe dll_target = $(buildlib)/$1.dll soname = dll_symlinks = install_symlinks = ipelet_target = $(BUILDDIR)/ipelets/$1.dll ifdef IPEMXE # --------------- Cross compiling with MXE --------------- CXXFLAGS += -g -O2 CXX = i686-pc-mingw32-g++ CC = i686-pc-mingw32-gcc STRIP_TARGET = i686-pc-mingw32-strip $(TARGET) WINDRES = i686-pc-mingw32-windres IPEDEPS := /sw/mingw QT_CFLAGS := -I/sw/mxe/usr/i686-pc-mingw32/include/QtGui \ -I/sw/mxe/usr/i686-pc-mingw32/include/QtCore \ -I/sw/mxe/usr/i686-pc-mingw32/include/Qt QT_LIBS := /sw/mxe/usr/i686-pc-mingw32/lib/QtCore4.dll \ /sw/mxe/usr/i686-pc-mingw32/lib/QtGui4.dll MOC ?= i686-pc-mingw32-moc else ifdef MINGWCROSS # --------------- Cross compiling with MinGW32 --------------- CXXFLAGS += -g -O2 CXX = i586-mingw32msvc-g++ CC = i586-mingw32msvc-gcc STRIP_TARGET = i586-mingw32msvc-strip $(TARGET) WINDRES = i586-mingw32msvc-windres IPEDEPS := /sw/mingw else # --------------- Compiling with MinGW32 under Windows --------------- WINDRES = C:/MinGW/bin/windres.exe CXXFLAGS += -g -O2 QTHOME := E:/Qt/4.8.4 IPEDEPS := E:/IpeDeps QT_CFLAGS := -I$(QTHOME)/include/QtGui \ -I$(QTHOME)/include/QtCore \ -I$(QTHOME)/include QT_LIBS := $(QTHOME)/bin/QtCore4.dll $(QTHOME)/bin/QtGui4.dll MOC ?= $(QTHOME)/bin/moc.exe endif ZLIB_CFLAGS := -I$(IPEDEPS)/include ZLIB_LIBS := $(IPEDEPS)/bin/zlib1.dll FREETYPE_CFLAGS := -I$(IPEDEPS)/include/freetype2 \ -I$(IPEDEPS)/include FREETYPE_LIBS := $(IPEDEPS)/bin/freetype6.dll CAIRO_CFLAGS := -I$(IPEDEPS)/include/cairo CAIRO_LIBS := $(IPEDEPS)/bin/libcairo-2.dll LUA_CFLAGS := -I$(IPEDEPS)/lua52/include LUA_LIBS := $(IPEDEPS)/lua52/lua52.dll else # -------------------- Unix -------------------- CXXFLAGS += -g -O2 ifdef MACOS DLL_LDFLAGS += -dynamiclib # IPELIBDIRINFO can be overridden as @executable_path/../lib # on the command line or by an environment variable IPELIBDIRINFO ?= $(IPELIBDIR) soname = -Wl,-dylib_install_name,$(IPELIBDIRINFO)/lib$1.so.$(IPEVERS) else DLL_LDFLAGS += -shared soname = -Wl,-soname,lib$1.so.$(IPEVERS) endif buildlib = $(BUILDDIR)/lib dll_target = $(buildlib)/lib$1.so.$(IPEVERS) dll_symlinks = ln -sf lib$1.so.$(IPEVERS) $(buildlib)/lib$1.so install_symlinks = ln -sf lib$1.so.$(IPEVERS) \ $(INSTALL_ROOT)$(IPELIBDIR)/lib$1.so ipelet_target = $(BUILDDIR)/ipelets/$1.so exe_target = $(BUILDDIR)/bin/$1 endif # Macros INSTALL_DIR = install -d INSTALL_FILES = install -m 0644 INSTALL_SCRIPTS = install -m 0755 ifdef MACOS # stripping is faulty on Mac? INSTALL_PROGRAMS = install -m 0755 else INSTALL_PROGRAMS = install -s -m 0755 endif MAKE_BINDIR = mkdir -p $(BUILDDIR)/bin MAKE_LIBDIR = mkdir -p $(buildlib) MAKE_IPELETDIR = mkdir -p $(BUILDDIR)/ipelets MAKE_DEPEND = \ mkdir -p $(OBJDIR); \ echo "" > $@; \ for f in $(all_sources); do \ $(CXX) -MM -MT $(OBJDIR)/$${f%%.cpp}.o $(CPPFLAGS) $$f >> $@; done # The rules $(OBJDIR)/%.o: %.cpp @echo Compiling $(unsnappedPos(); iCanvas->setCursor(CanvasBase::EHandCursor); } void PanTool::draw(Painter &painter) const { painter.translate(iPan); painter.setStroke(Attribute(Color(0, 0, 1000))); painter.newPath(); const Layout *l = iCanvas->cascade()->findLayout(); painter.rect(Rect(-l->iOrigin, -l->iOrigin + l->iPaperSize)); painter.drawPath(EStrokedOnly); for (int i = 0; i < iPage->count(); ++i) { if (iPage->objectVisible(iView, i)) iPage->object(i)->drawSimple(painter); } } void PanTool::mouseButton(int button, bool press) { if (!press) { Vector dpan = iCanvas->unsnappedPos() - iMouseDown; iCanvas->setPan(iCanvas->pan() - dpan); } iCanvas->finishTool(); } void PanTool::mouseMove() { iPan = iCanvas->unsnappedPos() - iMouseDown; iCanvas->updateTool(); } // -------------------------------------------------------------------- /*! \class ipe::SelectTool \ingroup canvas \brief A tool for selecting objects. */ class SelectCompare { public: int operator()(const SelectTool::SObj &lhs, const SelectTool::SObj &rhs) const { return (lhs.distance < rhs.distance); } }; //! Constructor starts selection. SelectTool::SelectTool(CanvasBase *canvas, Page *page, int view, double selectDistance, bool nonDestructive) : Tool(canvas) { iPage = page; iView = view; iNonDestructive = nonDestructive; iSelectDistance = selectDistance; // coordinates in user space Vector v = iCanvas->unsnappedPos(); iMouseDown = v; iDragging = false; double bound = iSelectDistance / iCanvas->zoom(); // Collect objects close enough double d; for (int i = iPage->count() - 1; i >= 0; --i) { if (iPage->objectVisible(iView, i) && !iPage->isLocked(iPage->layerOf(i))) { if ((d = iPage->distance(i, v, bound)) < bound) { SObj obj; obj.index = i; obj.distance = d; iObjs.push_back(obj); } } } iCur = 0; std::stable_sort(iObjs.begin(), iObjs.end(), SelectCompare()); iCanvas->setCursor(CanvasBase::ECrossCursor); } void SelectTool::draw(Painter &painter) const { if (iDragging) { Rect r(iMouseDown, iCorner); painter.setStroke(Attribute(Color(1000, 0, 1000))); painter.newPath(); painter.rect(r); painter.drawPath(EStrokedOnly); } else { painter.setStroke(Attribute(Color(1000, 0, 1000))); painter.newPath(); double d = iSelectDistance / iCanvas->zoom(); painter.drawArc(Arc(Matrix(d, 0, 0, d, iMouseDown.x, iMouseDown.y))); painter.closePath(); painter.drawPath(EStrokedOnly); if (iObjs.size() > 0) { // display current object painter.setStroke(Attribute(Color(1000, 0, 0))); iPage->object(iObjs[iCur].index)->drawSimple(painter); } } } void SelectTool::mouseButton(int button, bool press) { if (press) { iCanvas->finishTool(); return; } bool changed = false; if (iDragging) { Rect r(iMouseDown, iCorner); if (iNonDestructive) { // xor selection status of objects in range // last object that is not selected is made primary selection int new_primary = -1; for (int i = 0; i < iPage->count(); ++i) { Matrix id; if (iPage->objectVisible(iView, i)) { Rect s; iPage->object(i)->addToBBox(s, id, false); if (r.contains(s)) { changed = true; // in range if (iPage->select(i)) iPage->setSelect(i, ENotSelected); else { new_primary = i; iPage->setSelect(i, ESecondarySelected); } } } } if (new_primary >= 0) { // deselect old primary, select new primary int old_primary = iPage->primarySelection(); if (old_primary >= 0) iPage->setSelect(old_primary, ESecondarySelected); iPage->setSelect(new_primary, EPrimarySelected); } } else { // deselect all objects outside range, // secondary select all objects in range, for (int i = 0; i < iPage->count(); ++i) { iPage->setSelect(i, ENotSelected); Matrix id; if (iPage->objectVisible(iView, i)) { Rect s; iPage->object(i)->addToBBox(s, id, false); if (r.contains(s)) iPage->setSelect(i, ESecondarySelected); } } changed = true; // XXX this isn't accurate iPage->ensurePrimarySelection(); } } else if (iObjs.size() > 0) { int index = iObjs[iCur].index; if (iNonDestructive) { if (!iPage->select(index)) { // selecting unselected object as primary int old = iPage->primarySelection(); if (old >= 0) iPage->setSelect(old, ESecondarySelected); iPage->setSelect(index, EPrimarySelected); } else // deselecting selected object iPage->setSelect(index, ENotSelected); changed = true; iPage->ensurePrimarySelection(); } else { // destructive: unselect all for (int i = 0; i < iPage->count(); ++i) { if (i != index && iPage->select(i)) { changed = true; iPage->setSelect(i, ENotSelected); } } if (iPage->select(index) != EPrimarySelected) changed = true; iPage->setSelect(index, EPrimarySelected); } } else { // no object in range, deselect all if (!iNonDestructive) { changed = iPage->hasSelection(); iPage->deselectAll(); } } iCanvas->finishTool(); // not using right now (void) changed; } void SelectTool::mouseMove() { iCorner = iCanvas->unsnappedPos(); if ((iCorner - iMouseDown).sqLen() > 9.0) iDragging = true; iCanvas->updateTool(); } bool SelectTool::key(int code, int modifiers, String text) { if (!iDragging && code == ' ' && iObjs.size() > 0) { iCur++; if (iCur >= int(iObjs.size())) iCur = 0; iCanvas->updateTool(); return true; } else if (text == "\e") { iCanvas->finishTool(); return true; } else return false; } // -------------------------------------------------------------------- /*! \class ipe::TransformTool \ingroup canvas \brief A tool for transforming the selected objects on the canvas. Supports moving, rotating, scaling, and stretching. */ //! Constructor starts transformation. /*! After constructing a TransformTool, you must call isValid() to ensure that the transformation can be performed. A transformation can fail because the selection contains pinned objects, or because the initial mouse position is identical to the transformation origin. */ TransformTool::TransformTool(CanvasBase *canvas, Page *page, int view, TType type, bool withShift) : Tool(canvas) { iPage = page; iView = view; iType = type; iWithShift = withShift; iMouseDown = iCanvas->pos(); if (iType == ETranslate) iCanvas->setAutoOrigin(iMouseDown); iOnlyHorizontal = false; iOnlyVertical = false; iValid = true; // check if objects are pinned TPinned pin = ENoPin; for (int i = 0; i < page->count(); ++i) { if (page->select(i)) pin = TPinned(pin | page->object(i)->pinned()); } // rotating, scaling, and stretching are not allowed on pinned objects if (pin == EFixedPin || (pin && iType != ETranslate)) { iValid = false; return; } if (pin) { if (pin == EVerticalPin) iOnlyHorizontal = true; else iOnlyVertical = true; iWithShift = false; // ignore this and follow pinning restriction } // compute origin const Snap &sd = iCanvas->snap(); if (sd.iWithAxes) { iOrigin = sd.iOrigin; } else { // find bounding box of selected objects Rect bbox; for (int i = 0; i < iPage->count(); ++i) { if (iPage->select(i)) bbox.addRect(iPage->bbox(i)); } iOrigin = 0.5 * (bbox.bottomLeft() + bbox.topRight()); if (iType == EStretch || iType == EScale) { if (iMouseDown.x > iOrigin.x) iOrigin.x = bbox.bottomLeft().x; else iOrigin.x = bbox.topRight().x; if (iMouseDown.y > iOrigin.y) iOrigin.y = bbox.bottomLeft().y; else iOrigin.y = bbox.topRight().y; } } if (iType != ETranslate && iMouseDown == iOrigin) iValid = false; else iCanvas->setCursor(CanvasBase::EHandCursor); } //! Check that the transformation can be performed. bool TransformTool::isValid() const { return iValid; } void TransformTool::draw(Painter &painter) const { painter.setStroke(Attribute(Color(0, 600, 0))); painter.transform(iTransform); for (int i = 0; i < iPage->count(); ++i) { if (iPage->select(i)) iPage->object(i)->drawSimple(painter); } } // compute iTransform void TransformTool::compute(const Vector &v1) { Vector u0 = iMouseDown - iOrigin; Vector u1 = v1 - iOrigin; switch (iType) { case ETranslate: { Vector d = v1 - iMouseDown; if (iOnlyHorizontal || (iWithShift && ipe::abs(d.x) > ipe::abs(d.y))) d.y = 0.0; else if (iOnlyVertical || iWithShift) d.x = 0.0; iTransform = Matrix(d); break; } case ERotate: iTransform = (Matrix(iOrigin) * Linear(Angle(u1.angle() - u0.angle())) * Matrix(-iOrigin)); break; case EScale: { double factor = sqrt(u1.sqLen() / u0.sqLen()); iTransform = (Matrix(iOrigin) * Linear(factor, 0, 0, factor) * Matrix(-iOrigin)); break; } case EStretch: { double xfactor = (abs(u0.x) < EPS) ? 1.0 : u1.x / u0.x; double yfactor = (abs(u0.y) < EPS) ? 1.0 : u1.y / u0.y; iTransform = (Matrix(iOrigin) * Linear(xfactor, 0, 0, yfactor) * Matrix(-iOrigin)); break; } } } void TransformTool::mouseButton(int button, bool press) { if (!press) { compute(iCanvas->pos()); report(); } iCanvas->finishTool(); } //! Report the final transformation chosen. /*! The implementation in TransformTool does nothing. Derived classes should reimplement report(). */ void TransformTool::report() { // nothing yet } void TransformTool::mouseMove() { compute(iCanvas->pos()); iCanvas->updateTool(); } // -------------------------------------------------------------------- ipe-7.1.4/src/ipecanvas/ipetool.h0000644000175000017500000000722712120621776016552 0ustar otfriedotfried// -*- C++ -*- // -------------------------------------------------------------------- // ipe::Tool // -------------------------------------------------------------------- /* This file is part of the extensible drawing editor Ipe. Copyright (C) 1993-2013 Otfried Cheong Ipe is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. As a special exception, you have permission to link Ipe with the CGAL library and distribute executables, as long as you follow the requirements of the Gnu General Public License in regard to all of the software in the executable aside from CGAL. Ipe 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 General Public License for more details. You should have received a copy of the GNU General Public License along with Ipe; if not, you can find it at "http://www.gnu.org/copyleft/gpl.html", or write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ #ifndef IPETOOL_H #define IPETOOL_H #include "ipelib.h" using namespace ipe; namespace ipe { class CanvasBase; class Tool { public: virtual ~Tool(); public: virtual void draw(Painter &painter) const = 0; virtual void mouseButton(int button, bool press); virtual void mouseMove(); virtual bool key(int code, int modifiers, String text); protected: Tool(CanvasBase *canvas); protected: CanvasBase *iCanvas; }; // -------------------------------------------------------------------- class PanTool : public Tool { public: PanTool(CanvasBase *canvas, const Page *page, int view); virtual void draw(Painter &painter) const; virtual void mouseButton(int button, bool press); virtual void mouseMove(); private: const Page *iPage; int iView; Vector iPan; Vector iMouseDown; }; // -------------------------------------------------------------------- class SelectTool : public Tool { public: SelectTool(CanvasBase *canvas, Page *page, int view, double selectDistance, bool nonDestructive); virtual void draw(Painter &painter) const; virtual void mouseButton(int button, bool press); virtual void mouseMove(); virtual bool key(int code, int modifiers, String text); private: void ensurePrimary(); public: struct SObj { int index; double distance; }; private: Page *iPage; int iView; bool iNonDestructive; double iSelectDistance; Vector iMouseDown; std::vector iObjs; int iCur; bool iDragging; Vector iCorner; }; // -------------------------------------------------------------------- class TransformTool : public Tool { public: enum TType { ETranslate, EScale, EStretch, ERotate }; TransformTool(CanvasBase *canvas, Page *page, int view, TType type, bool withShift); bool isValid() const; virtual void draw(Painter &painter) const; virtual void mouseButton(int button, bool press); virtual void mouseMove(); virtual void report(); protected: void compute(const Vector &v); protected: Page *iPage; int iView; TType iType; bool iWithShift; bool iOnlyHorizontal; bool iOnlyVertical; Vector iMouseDown; Matrix iTransform; Vector iOrigin; bool iValid; }; } // namespace // -------------------------------------------------------------------- #endif ipe-7.1.4/src/ipecanvas/ipecanvas_win.cpp0000644000175000017500000001710512120621776020254 0ustar otfriedotfried// -------------------------------------------------------------------- // ipe::Canvas for Win // -------------------------------------------------------------------- /* This file is part of the extensible drawing editor Ipe. Copyright (C) 1993-2013 Otfried Cheong Ipe is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. As a special exception, you have permission to link Ipe with the CGAL library and distribute executables, as long as you follow the requirements of the Gnu General Public License in regard to all of the software in the executable aside from CGAL. Ipe 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 General Public License for more details. You should have received a copy of the GNU General Public License along with Ipe; if not, you can find it at "http://www.gnu.org/copyleft/gpl.html", or write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ #include "ipecanvas_win.h" #include "ipecairopainter.h" #include "ipetool.h" #include #include #include using namespace ipe; const char Canvas::className[] = "ipeCanvasWindowClass"; // -------------------------------------------------------------------- void Canvas::invalidate() { InvalidateRect(hwnd, NULL, FALSE); } void Canvas::invalidate(int x, int y, int w, int h) { RECT r; r.left = x; r.right = x + w; r.top = y; r.bottom = y + h; // ipeDebug("invalidate %d %d %d %d\n", r.left, r.right, r.top, r.bottom); InvalidateRect(hwnd, &r, FALSE); } // -------------------------------------------------------------------- int Canvas::getModifiers() { int mod = 0; if (GetKeyState(VK_SHIFT)) mod |= EShift; if (GetKeyState(VK_CONTROL)) mod |= EControl; if (GetKeyState(VK_MENU)) mod |= EAlt; return mod; } void Canvas::button(int button, bool down, int xPos, int yPos) { // ipeDebug("Canvas::button %d %d %d %d", button, down, xPos, yPos); POINT p; p.x = xPos; p.y = yPos; ClientToScreen(hwnd, &p); iGlobalPos = Vector(p.x, p.y); computeFifi(xPos, yPos); int mod = getModifiers() | iAdditionalModifiers; if (iTool) iTool->mouseButton(button | mod, down); else if (down && iObserver) iObserver->canvasObserverMouseAction(button | mod); } void Canvas::mouseMove(int xPos, int yPos) { // ipeDebug("Canvas::mouseMove %d %d", xPos, yPos); computeFifi(xPos, yPos); if (iTool) iTool->mouseMove(); if (iObserver) iObserver->canvasObserverPositionChanged(); } void Canvas::wheel(int zDelta) { // ipeDebug("Canvas::wheel %d", zDelta); if (iObserver) iObserver->canvasObserverWheelMoved(zDelta); } void Canvas::setCursor(TCursor cursor, double w, Color *color) { // TODO } // -------------------------------------------------------------------- void Canvas::updateSize() { RECT rc; GetClientRect(hwnd, &rc); iWidth = rc.right; iHeight = rc.bottom; } void Canvas::wndPaint() { PAINTSTRUCT ps; HDC hdc = BeginPaint(hwnd, &ps); if (!iWidth) updateSize(); refreshSurface(); int x0 = ps.rcPaint.left; int y0 = ps.rcPaint.top; int w = ps.rcPaint.right - x0; int h = ps.rcPaint.bottom - y0; HBITMAP bits = CreateCompatibleBitmap(hdc, w, h); HDC bitsDC = CreateCompatibleDC(hdc); SelectObject(bitsDC, bits); cairo_surface_t *surface = cairo_win32_surface_create(bitsDC); cairo_t *cr = cairo_create(surface); cairo_translate(cr, -x0, -y0); cairo_set_source_surface(cr, iSurface, 0.0, 0.0); cairo_paint(cr); if (iFifiVisible) { Vector p = userToDev(iMousePos); cairo_set_source_rgb(cr, 1.0, 0.0, 0.0); cairo_move_to(cr, p.x - 8, p.y); cairo_line_to(cr, p.x + 8, p.y); cairo_move_to(cr, p.x, p.y - 8); cairo_line_to(cr, p.x, p.y + 8); cairo_stroke(cr); iOldFifi = p; } if (iPage) { CairoPainter cp(iCascade, iFonts, cr, iZoom, false); cp.transform(canvasTfm()); cp.pushMatrix(); drawTool(cp); cp.popMatrix(); } cairo_destroy(cr); cairo_surface_destroy(surface); BitBlt(hdc, x0, y0, w, h, bitsDC, 0, 0, SRCCOPY); DeleteDC(bitsDC); DeleteObject(bits); EndPaint(hwnd, &ps); } // -------------------------------------------------------------------- void Canvas::mouseButton(Canvas *canvas, int button, bool down, LPARAM lParam) { if (canvas) { int xPos = GET_X_LPARAM(lParam); int yPos = GET_Y_LPARAM(lParam); canvas->button(button, down, xPos, yPos); } } LRESULT CALLBACK Canvas::wndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) { Canvas *canvas = (Canvas *) GetWindowLongPtr(hwnd, GWLP_USERDATA); switch (message) { case WM_CREATE: { assert(canvas == 0); LPCREATESTRUCT p = (LPCREATESTRUCT) lParam; canvas = (Canvas *) p->lpCreateParams; canvas->hwnd = hwnd; SetWindowLongPtr(hwnd, GWLP_USERDATA, (LONG_PTR) canvas); } break; case WM_PAINT: if (canvas) canvas->wndPaint(); return 0; case WM_MOUSEMOVE: if (canvas) { int xPos = GET_X_LPARAM(lParam); int yPos = GET_Y_LPARAM(lParam); canvas->mouseMove(xPos, yPos); } break; case WM_SIZE: if (canvas) canvas->updateSize(); break; case WM_LBUTTONDOWN: mouseButton(canvas, 1, true, lParam); break; case WM_LBUTTONUP: mouseButton(canvas, 1, false, lParam); break; case WM_RBUTTONDOWN: mouseButton(canvas, 2, true, lParam); break; case WM_RBUTTONUP: mouseButton(canvas, 2, false, lParam); break; case WM_MBUTTONDOWN: mouseButton(canvas, 3, true, lParam); break; case WM_MBUTTONUP: mouseButton(canvas, 3, false, lParam); break; case WM_MOUSEWHEEL: if (canvas) canvas->wheel(GET_WHEEL_DELTA_WPARAM(wParam)); break; case WM_GETMINMAXINFO: { LPMINMAXINFO mm = LPMINMAXINFO(lParam); fprintf(stderr, "Canvas MINMAX %ld %ld\n", mm->ptMinTrackSize.x, mm->ptMinTrackSize.y); } break; case WM_DESTROY: delete canvas; break; default: // ipeDebug("Canvas wndProc(%d)", message); break; } return DefWindowProc(hwnd, message, wParam, lParam); } // -------------------------------------------------------------------- Canvas::Canvas(HWND parent) { HWND hwnd = CreateWindowEx(WS_EX_CLIENTEDGE, className, "", WS_CHILD | WS_VISIBLE, 0, 0, 0, 0, parent, NULL, (HINSTANCE) GetWindowLong(parent, GWL_HINSTANCE), this); if (hwnd == NULL) { MessageBox(NULL, "Canvas creation failed!", "Error!", MB_ICONEXCLAMATION | MB_OK); exit(9); } assert(GetWindowLongPtr(hwnd, GWLP_USERDATA)); } void Canvas::init(HINSTANCE hInstance) { WNDCLASSEX wc; wc.cbSize = sizeof(WNDCLASSEX); wc.style = 0; // CS_VREDRAW | CS_HREDRAW; wc.lpfnWndProc = wndProc; wc.cbClsExtra = 0; wc.cbWndExtra = 0; wc.hInstance = hInstance; wc.hCursor = LoadCursor(NULL, IDC_ARROW); wc.hbrBackground = (HBRUSH) GetStockObject(NULL_BRUSH); wc.lpszMenuName = NULL; // actually child id wc.lpszClassName = className; wc.hIcon = NULL; wc.hIconSm = NULL; if (!RegisterClassEx(&wc)) { MessageBox(NULL, "Canvas control registration failed!", "Error!", MB_ICONEXCLAMATION | MB_OK); exit(9); } } void ipe_init_canvas(HINSTANCE hInstance) { Canvas::init(hInstance); } // -------------------------------------------------------------------- ipe-7.1.4/src/ipecanvas/ipecanvas_gtk.h0000644000175000017500000000473112120621776017712 0ustar otfriedotfried// -*- C++ -*- // -------------------------------------------------------------------- // ipe::Canvas for GTK // -------------------------------------------------------------------- /* This file is part of the extensible drawing editor Ipe. Copyright (C) 1993-2013 Otfried Cheong Ipe is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. As a special exception, you have permission to link Ipe with the CGAL library and distribute executables, as long as you follow the requirements of the Gnu General Public License in regard to all of the software in the executable aside from CGAL. Ipe 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 General Public License for more details. You should have received a copy of the GNU General Public License along with Ipe; if not, you can find it at "http://www.gnu.org/copyleft/gpl.html", or write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ #ifndef IPECANVAS_GTK_H #define IPECANVAS_GTK_H // -------------------------------------------------------------------- #include "ipecanvas.h" #include namespace ipe { class Canvas : public CanvasBase { public: Canvas(GtkWidget *parent); ~Canvas(); GtkWidget *window() const { return GTK_WIDGET(iWindow); } private: virtual void setCursor(TCursor cursor, double w = 1.0, Color *color = 0); virtual void invalidate(); virtual void invalidate(int x, int y, int w, int h); void exposeHandler(GdkEventExpose *event); void buttonHandler(GdkEventButton *event); void motionHandler(GdkEventMotion *event); void scrollHandler(GdkEventScroll *event); static gboolean expose_cb(GtkWidget *widget, GdkEvent *event, Canvas *canvas); static gboolean button_cb(GtkWidget *widget, GdkEvent *event, Canvas *data); static gboolean motion_cb(GtkWidget *widget, GdkEvent *event, Canvas *canvas); static gboolean scroll_cb(GtkWidget *widget, GdkEvent *event, Canvas *canvas); private: GtkWidget *iWindow; }; } // namespace // -------------------------------------------------------------------- #endif ipe-7.1.4/src/ipecanvas/Makefile0000644000175000017500000000236012120621776016357 0ustar otfriedotfried# -------------------------------------------------------------------- # Makefile for ipe::Canvas # -------------------------------------------------------------------- OBJDIR = $(BUILDDIR)/obj/ipecanvas include ../common.mak TARGET = $(call dll_target,ipecanvas) MAKE_SYMLINKS = $(call dll_symlinks,ipecanvas) SONAME = $(call soname,ipecanvas) INSTALL_SYMLINKS = $(call install_symlinks,ipecanvas) CPPFLAGS += -I../include -I../ipecairo $(CAIRO_CFLAGS) $(UI_CFLAGS) LIBS += -L$(buildlib) -lipecairo -lipe $(CAIRO_LIBS) $(UI_LIBS) CXXFLAGS += $(DLL_CFLAGS) all: $(TARGET) sources = ipetool.cpp ipecanvas.cpp win_sources = ipecanvas_win.cpp gtk_sources = ipecanvas_gtk.cpp qt_sources = ipecanvas_qt.cpp ipeselector_qt.cpp moc_headers = ipecanvas_qt.h ipeselector_qt.h $(TARGET): $(objects) $(MAKE_LIBDIR) $(CXX) $(LDFLAGS) $(DLL_LDFLAGS) $(SONAME) -o $@ $^ $(LIBS) $(MAKE_SYMLINKS) clean: @-rm -f $(objects) $(TARGET) $(DEPEND) $(DEPEND): Makefile $(MAKE_DEPEND) -include $(DEPEND) install: $(TARGET) $(INSTALL_DIR) $(INSTALL_ROOT)$(IPELIBDIR) $(INSTALL_PROGRAMS) $(TARGET) $(INSTALL_ROOT)$(IPELIBDIR) $(INSTALL_FILES) *.h $(INSTALL_ROOT)$(IPEHEADERDIR) $(INSTALL_SYMLINKS) # -------------------------------------------------------------------- ipe-7.1.4/src/ipecanvas/ipecanvas_win.h0000644000175000017500000000457112120621776017724 0ustar otfriedotfried// -*- C++ -*- // -------------------------------------------------------------------- // ipe::Canvas for Win32 // -------------------------------------------------------------------- /* This file is part of the extensible drawing editor Ipe. Copyright (C) 1993-2013 Otfried Cheong Ipe is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. As a special exception, you have permission to link Ipe with the CGAL library and distribute executables, as long as you follow the requirements of the Gnu General Public License in regard to all of the software in the executable aside from CGAL. Ipe 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 General Public License for more details. You should have received a copy of the GNU General Public License along with Ipe; if not, you can find it at "http://www.gnu.org/copyleft/gpl.html", or write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ #ifndef IPECANVASWIN_H #define IPECANVASWIN_H // -------------------------------------------------------------------- #include "ipecanvas.h" #include namespace ipe { class Canvas : public CanvasBase { public: static void init(HINSTANCE hInstance); Canvas(HWND parent); HWND windowId() const { return hwnd; } private: int getModifiers(); void button(int button, bool down, int xPos, int yPos); void mouseMove(int xPos, int yPos); void wheel(int zDelta); void wndPaint(); void updateSize(); virtual void invalidate(); virtual void invalidate(int x, int y, int w, int h); virtual void setCursor(TCursor cursor, double w, Color *color); private: static const char className[]; static LRESULT CALLBACK wndProc(HWND hwnd, UINT Message, WPARAM wParam, LPARAM lParam); static void mouseButton(Canvas *canvas, int button, bool down, LPARAM lParam); private: HWND hwnd; }; } // namespace extern void ipe_init_canvas(HINSTANCE hInstance); // -------------------------------------------------------------------- #endif ipe-7.1.4/src/ipecanvas/ipeselector_qt.cpp0000644000175000017500000001145112120621776020446 0ustar otfriedotfried// -------------------------------------------------------------------- // PageSelector for QT // -------------------------------------------------------------------- /* This file is part of the extensible drawing editor Ipe. Copyright (C) 1993-2013 Otfried Cheong Ipe is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. As a special exception, you have permission to link Ipe with the CGAL library and distribute executables, as long as you follow the requirements of the Gnu General Public License in regard to all of the software in the executable aside from CGAL. Ipe 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 General Public License for more details. You should have received a copy of the GNU General Public License along with Ipe; if not, you can find it at "http://www.gnu.org/copyleft/gpl.html", or write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ #include "ipeselector_qt.h" #include "ipethumbs.h" #include #include using namespace ipe; // -------------------------------------------------------------------- /*! \class ipeqt::PageSelector \ingroup qtcanvas \brief A Qt widget that displays a list of Ipe pages. */ //! Construct the widget. /*! If \a page is negative, the last view of each page is shown. Otherwise, all views of this page are shown. \a itemWidth is the width of the page thumbnails (the height is computed automatically). */ PageSelector::PageSelector(Document *doc, int page, int startIndex, int itemWidth, QWidget *parent) : QListWidget(parent) { iDoc = doc; setViewMode(QListView::IconMode); setSelectionMode(QAbstractItemView::SingleSelection); setResizeMode(QListView::Adjust); setWrapping(true); setUniformItemSizes(true); setFlow(QListView::LeftToRight); setSpacing(10); setMovement(QListView::Static); Thumbnail r(iDoc, itemWidth); setGridSize(QSize(itemWidth, r.height() + 50)); setIconSize(QSize(itemWidth, r.height())); if (page >= 0) { Page *p = doc->page(page); for (int i = 0; i < p->countViews(); ++i) { Buffer b = r.render(p, i); QImage bits((const uchar *) b.data(), itemWidth, r.height(), QImage::Format_RGB32); // need to copy bits since buffer b is temporary QIcon icon(QPixmap::fromImage(bits.copy())); QString s; s.sprintf("View %d", i+1); QListWidgetItem *item = new QListWidgetItem(icon, s); item->setFlags(Qt::ItemIsSelectable|Qt::ItemIsEnabled); item->setToolTip(s); addItem(item); } } else { for (int i = 0; i < doc->countPages(); ++i) { Page *p = doc->page(i); Buffer b = r.render(p, p->countViews() - 1); QImage bits((const uchar *) b.data(), itemWidth, r.height(), QImage::Format_RGB32); // need to copy bits since buffer b is temporary QIcon icon(QPixmap::fromImage(bits.copy())); QString s; QString t = QString::fromUtf8(p->title().z()); if (t != "") { s.sprintf("%d: ", i+1); s += t; } else { s.sprintf("Page %d", i+1); } QListWidgetItem *item = new QListWidgetItem(icon, s); item->setFlags(Qt::ItemIsSelectable|Qt::ItemIsEnabled); item->setToolTip(s); addItem(item); } } setCurrentRow(startIndex); connect(this, SIGNAL(itemActivated(QListWidgetItem *)), SLOT(pageSelected(QListWidgetItem *))); } void PageSelector::pageSelected(QListWidgetItem *item) { emit selectionMade(); } // -------------------------------------------------------------------- //! Show dialog to select a page or a view. /*! If \a page is negative (the default), shows thumbnails of all pages of the document in a dialog. If the user selects a page, the page number is returned. If the dialog is canceled, -1 is returned. If \a page is non-negative, all views of this page are shown, and the selected view number is returned. */ int PageSelector::selectPageOrView(Document *doc, int page, int startIndex, int pageWidth, int width, int height) { QDialog *d = new QDialog(); d->setWindowTitle("Select page"); QLayout *lo = new QVBoxLayout; PageSelector *p = new PageSelector(doc, page, startIndex, pageWidth); lo->addWidget(p); d->setLayout(lo); connect(p, SIGNAL(selectionMade()), d, SLOT(accept())); d->resize(width, height); int result = d->exec(); int sel = p->selectedIndex(); delete d; return (result == QDialog::Rejected) ? -1 : sel; } // -------------------------------------------------------------------- ipe-7.1.4/src/ipecanvas/ipecanvas_qt.h0000644000175000017500000000560312120621776017550 0ustar otfriedotfried// -*- C++ -*- // -------------------------------------------------------------------- // ipe::Canvas for QT // -------------------------------------------------------------------- /* This file is part of the extensible drawing editor Ipe. Copyright (C) 1993-2013 Otfried Cheong Ipe is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. As a special exception, you have permission to link Ipe with the CGAL library and distribute executables, as long as you follow the requirements of the Gnu General Public License in regard to all of the software in the executable aside from CGAL. Ipe 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 General Public License for more details. You should have received a copy of the GNU General Public License along with Ipe; if not, you can find it at "http://www.gnu.org/copyleft/gpl.html", or write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ #ifndef IPECANVAS_QT_H #define IPECANVAS_QT_H #include "ipecanvas.h" #include // -------------------------------------------------------------------- namespace ipe { inline QPointF QPt(const Vector &v) { return QPointF(v.x, v.y); } inline String IpeQ(const QString &str) { return String(str.toUtf8()); } inline QString QIpe(const String &str) { return QString::fromUtf8(str.z()); } inline QColor QIpe(Color color) { return QColor(int(color.iRed.toDouble() * 255 + 0.5), int(color.iGreen.toDouble() * 255 + 0.5), int(color.iBlue.toDouble() * 255 + 0.5)); } inline Color IpeQ(QColor color) { return Color(color.red() * 1000 / 255, color.green() * 1000 / 255, color.blue() * 1000 / 255); } // -------------------------------------------------------------------- class Canvas : public QWidget, public CanvasBase { Q_OBJECT public: Canvas(QWidget* parent, Qt::WFlags f=0); virtual void setCursor(TCursor cursor, double w = 1.0, Color *color = 0); protected: virtual void invalidate(); virtual void invalidate(int x, int y, int w, int h); protected: virtual void paintEvent(QPaintEvent *ev); virtual void mousePressEvent(QMouseEvent *ev) ; virtual void mouseReleaseEvent(QMouseEvent *ev); virtual void mouseMoveEvent(QMouseEvent *ev); virtual void tabletEvent(QTabletEvent *ev); virtual void wheelEvent(QWheelEvent *ev); virtual void keyPressEvent(QKeyEvent *ev); virtual QSize sizeHint() const; }; } // namespace // -------------------------------------------------------------------- #endif ipe-7.1.4/src/ipecanvas/ipeselector_qt.h0000644000175000017500000000407612120621776020120 0ustar otfriedotfried// -*- C++ -*- // -------------------------------------------------------------------- // ipeqt::PageSelector // -------------------------------------------------------------------- /* This file is part of the extensible drawing editor Ipe. Copyright (C) 1993-2013 Otfried Cheong Ipe is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. As a special exception, you have permission to link Ipe with the CGAL library and distribute executables, as long as you follow the requirements of the Gnu General Public License in regard to all of the software in the executable aside from CGAL. Ipe 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 General Public License for more details. You should have received a copy of the GNU General Public License along with Ipe; if not, you can find it at "http://www.gnu.org/copyleft/gpl.html", or write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ #ifndef IPESELECTOR_H #define IPESELECTOR_H #include "ipedoc.h" #include using namespace ipe; // -------------------------------------------------------------------- namespace ipe { class PageSelector : public QListWidget { Q_OBJECT public: PageSelector(Document *doc, int page, int startIndex, int width, QWidget *parent = 0); int selectedIndex() const { return currentRow(); } static int selectPageOrView(Document *doc, int page = -1, int startIndex = 0, int pageWidth = 240, int width = 600, int height = 480); signals: void selectionMade(); private slots: void pageSelected(QListWidgetItem *item); private: Document *iDoc; }; } // namespace // -------------------------------------------------------------------- #endif ipe-7.1.4/src/ipecanvas/ipecanvas_qt.cpp0000644000175000017500000001751412120621776020107 0ustar otfriedotfried// -------------------------------------------------------------------- // ipe::Canvas for Qt // -------------------------------------------------------------------- /* This file is part of the extensible drawing editor Ipe. Copyright (C) 1993-2013 Otfried Cheong Ipe is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. As a special exception, you have permission to link Ipe with the CGAL library and distribute executables, as long as you follow the requirements of the Gnu General Public License in regard to all of the software in the executable aside from CGAL. Ipe 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 General Public License for more details. You should have received a copy of the GNU General Public License along with Ipe; if not, you can find it at "http://www.gnu.org/copyleft/gpl.html", or write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ #include "ipecanvas_qt.h" #include "ipepainter.h" #include "ipetool.h" #include #include #include using namespace ipe; // -------------------------------------------------------------------- class IpeQtPainter : public Painter { public: IpeQtPainter(const Cascade *sheet, QPainter *painter); virtual ~IpeQtPainter(); protected: virtual void doNewPath(); virtual void doMoveTo(const Vector &v); virtual void doLineTo(const Vector &v); virtual void doCurveTo(const Vector &v1, const Vector &v2, const Vector &v3); virtual void doClosePath(); virtual void doDrawPath(TPathMode mode); private: QPainter *iQP; QPainterPath iPP; }; IpeQtPainter::IpeQtPainter(const Cascade *sheet, QPainter *painter) : Painter(sheet) { iQP = painter; } IpeQtPainter::~IpeQtPainter() { // nothing } void IpeQtPainter::doNewPath() { iPP = QPainterPath(); } void IpeQtPainter::doMoveTo(const Vector &v) { iPP.moveTo(QPt(v)); } void IpeQtPainter::doLineTo(const Vector &v) { iPP.lineTo(QPt(v)); } void IpeQtPainter::doCurveTo(const Vector &v1, const Vector &v2, const Vector &v3) { iPP.cubicTo(QPt(v1), QPt(v2), QPt(v3)); } void IpeQtPainter::doClosePath() { iPP.closeSubpath(); } void IpeQtPainter::doDrawPath(TPathMode mode) { if (mode >= EStrokedAndFilled) { QBrush qbrush(QIpe(fill())); iQP->fillPath(iPP, qbrush); } if (mode <= EStrokedAndFilled) { QPen qpen(QIpe(stroke())); qpen.setWidthF(pen().toDouble()); iQP->strokePath(iPP, qpen); } } // -------------------------------------------------------------------- //! Construct a new canvas. Canvas::Canvas(QWidget* parent, Qt::WFlags f) : QWidget(parent, f) { setAttribute(Qt::WA_NoBackground); setMouseTracking(true); setFocusPolicy(Qt::ClickFocus); } QSize Canvas::sizeHint() const { return QSize(640, 480); } void Canvas::setCursor(TCursor cursor, double w, Color *color) { switch (cursor) { case EStandardCursor: default: QWidget::unsetCursor(); break; case EHandCursor: QWidget::setCursor(QCursor(Qt::PointingHandCursor)); break; case ECrossCursor: QWidget::setCursor(QCursor(Qt::CrossCursor)); break; case EDotCursor: { QPixmap p(32, 32); p.fill(QColor(255, 255, 255, 0)); QPainter painter(&p); double s = 0.5 * w * zoom(); if (s < 1.0) s = 1.0; if (s > 10.0) s = 10.0; int r = 255 * color->iRed.internal() / 1000; int g = 255 * color->iGreen.internal() / 1000; int b = 255 * color->iBlue.internal() / 1000; painter.setBrush(QColor(r, g, b)); painter.setPen(Qt::NoPen); painter.drawEllipse(QRectF(16.0 - s, 16.0 - s, 2 * s, 2 * s)); painter.end(); QWidget::setCursor(QCursor(p)); } break; } } // -------------------------------------------------------------------- void Canvas::invalidate() { QWidget::update(); } void Canvas::invalidate(int x, int y, int w, int h) { QWidget::update(QRect(x, y, w, h)); } // -------------------------------------------------------------------- static int convertModifiers(int qmod) { int mod = 0; if (qmod & Qt::ShiftModifier) mod |= CanvasBase::EShift; if (qmod & Qt::ControlModifier) mod |= CanvasBase::EControl; if (qmod & Qt::AltModifier) mod |= CanvasBase::EAlt; if (qmod & Qt::MetaModifier) mod |= CanvasBase::EMeta; return mod; } void Canvas::keyPressEvent(QKeyEvent *ev) { String s = IpeQ(ev->text()); if (iTool && iTool->key(ev->key(), (convertModifiers(ev->modifiers()) | iAdditionalModifiers), s)) ev->accept(); else ev->ignore(); } void Canvas::mousePressEvent(QMouseEvent *ev) { iGlobalPos = Vector(ev->globalPos().x(), ev->globalPos().y()); computeFifi(ev->x(), ev->y()); int mod = convertModifiers(ev->modifiers()) | iAdditionalModifiers; if (iTool) iTool->mouseButton(ev->button() | mod, true); else if (iObserver) iObserver->canvasObserverMouseAction(ev->button() | mod); } void Canvas::mouseReleaseEvent(QMouseEvent *ev) { iGlobalPos = Vector(ev->globalPos().x(), ev->globalPos().y()); computeFifi(ev->x(), ev->y()); if (iTool) iTool->mouseButton(ev->button(), false); } void Canvas::mouseMoveEvent(QMouseEvent *ev) { computeFifi(ev->x(), ev->y()); if (iTool) iTool->mouseMove(); if (iObserver) iObserver->canvasObserverPositionChanged(); } void Canvas::tabletEvent(QTabletEvent *ev) { Vector globalPos(ev->hiResGlobalPos().x(), ev->hiResGlobalPos().y()); QPointF hiPos = ev->hiResGlobalPos() - (ev->globalPos() - ev->pos()); ev->accept(); switch (ev->type()) { case QEvent::TabletPress: iGlobalPos = globalPos; computeFifi(hiPos.x(), hiPos.y()); if (ev->pointerType() == QTabletEvent::Eraser) { if (iObserver) iObserver->canvasObserverMouseAction(Qt::XButton1 | iAdditionalModifiers); } else if (iTool) iTool->mouseButton(Qt::LeftButton | iAdditionalModifiers, true); else if (iObserver) iObserver->canvasObserverMouseAction(Qt::LeftButton | iAdditionalModifiers); break; case QEvent::TabletMove: if (ev->pressure() > 0.01) { computeFifi(hiPos.x(), hiPos.y()); if (iTool) iTool->mouseMove(); if (iObserver) iObserver->canvasObserverPositionChanged(); break; } // else fall through and consider it a release event case QEvent::TabletRelease: iGlobalPos = globalPos; computeFifi(hiPos.x(), hiPos.y()); if (iTool) iTool->mouseButton(Qt::LeftButton, false); break; default: ipeDebug("Unknown tablet event"); break; } } void Canvas::wheelEvent(QWheelEvent *ev) { if (iObserver) iObserver->canvasObserverWheelMoved(ev->delta()); ev->accept(); } void Canvas::paintEvent(QPaintEvent * ev) { iWidth = width(); iHeight = height(); refreshSurface(); QPainter qPainter; qPainter.begin(this); QRect r = ev->rect(); QImage bits(cairo_image_surface_get_data(iSurface), iWidth, iHeight, QImage::Format_RGB32); qPainter.drawImage(r.left(), r.top(), bits, r.left(), r.top(), r.width(), r.height()); qPainter.translate(-1, -1); if (iFifiVisible) { Vector p = userToDev(iMousePos); qPainter.setPen(QColor(255, 0, 0, 255)); qPainter.drawLine(QPt(p - Vector(8, 0)), QPt(p + Vector(8, 0))); qPainter.drawLine(QPt(p - Vector(0, 8)), QPt(p + Vector(0, 8))); iOldFifi = p; } // ----------------------------------- if (iPage) { IpeQtPainter qp(iCascade, &qPainter); qp.transform(canvasTfm()); qp.pushMatrix(); drawTool(qp); qp.popMatrix(); } qPainter.end(); } // -------------------------------------------------------------------- ipe-7.1.4/src/ipecanvas/ipecanvas.h0000644000175000017500000001331312120621776017041 0ustar otfriedotfried// -*- C++ -*- // -------------------------------------------------------------------- // ipe::Canvas // -------------------------------------------------------------------- /* This file is part of the extensible drawing editor Ipe. Copyright (C) 1993-2013 Otfried Cheong Ipe is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. As a special exception, you have permission to link Ipe with the CGAL library and distribute executables, as long as you follow the requirements of the Gnu General Public License in regard to all of the software in the executable aside from CGAL. Ipe 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 General Public License for more details. You should have received a copy of the GNU General Public License along with Ipe; if not, you can find it at "http://www.gnu.org/copyleft/gpl.html", or write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ #ifndef IPECANVAS_H #define IPECANVAS_H #include "ipelib.h" // -------------------------------------------------------------------- // Avoid including cairo.h typedef struct _cairo cairo_t; typedef struct _cairo_surface cairo_surface_t; // -------------------------------------------------------------------- namespace ipe { class Fonts; class Tool; // -------------------------------------------------------------------- class CanvasObserver { public: virtual void canvasObserverWheelMoved(int degrees); virtual void canvasObserverMouseAction(int button); virtual void canvasObserverPositionChanged(); virtual void canvasObserverToolChanged(bool hasTool); virtual void canvasObserverSizeChanged(); }; class CanvasBase { public: //! Keyboard modifiers enum TModifiers { EShift = 0x100, EControl = 0x200, EAlt = 0x400, EMeta = 0x800 }; enum TCursor { EStandardCursor, EHandCursor, ECrossCursor, EDotCursor }; /*! In pretty display, no dashed lines are drawn around text objects, and if Latex font data is not available, no text is drawn at all. */ struct Style { Color paperColor; bool pretty; bool classicGrid; double thinLine; double thickLine; int thinStep; int thickStep; bool paperClip; bool numberPages; }; virtual ~CanvasBase(); void setPage(const Page *page, int pno, int view, const Cascade *sheet); void setFontPool(const FontPool *fontPool); //! Return current pan. inline Vector pan() const { return iPan; } //! Return current zoom. inline double zoom() const { return iZoom; } //! Return current style sheet cascade. inline const Cascade *cascade() const { return iCascade; } //! Return center of canvas. inline Vector center() const {return 0.5 * Vector(iWidth, iHeight); } //! Return last mouse position (snapped!) in user coordinates. inline Vector pos() const { return iMousePos; } //! Return last unsnapped mouse position in user coordinates. inline Vector unsnappedPos() const { return iUnsnappedMousePos; } //! Return global mouse position of last mouse press/release. inline Vector globalPos() const { return iGlobalPos; } Vector simpleSnapPos() const; //! Return current snapping information. inline const Snap &snap() const { return iSnap; } //! Return current additional modifiers. inline int additionalModifiers() const { return iAdditionalModifiers; } void setAdditionalModifiers(int mod); Vector devToUser(const Vector &arg) const; Vector userToDev(const Vector &arg) const; void setCanvasStyle(const Style &style); //! Return canvas style Style canvasStyle() const { return iStyle; } void setPan(const Vector &v); void setZoom(double zoom); void setSnap(const Snap &s); void setDimmed(bool dimmed); void setAutoOrigin(const Vector &v); Matrix canvasTfm() const; void setObserver(CanvasObserver *observer); void setFifiVisible(bool visible); void setSelectionVisible(bool visible); void setTool(Tool *tool); void finishTool(); void update(); void updateTool(); int canvasWidth() const { return iWidth; } int canvasHeight() const { return iHeight; } virtual void setCursor(TCursor cursor, double w = 1.0, Color *color = 0) = 0; protected: CanvasBase(); void drawPaper(cairo_t *cc); void drawFrame(cairo_t *cc); void drawAxes(cairo_t *cc); void drawGrid(cairo_t *cc); void drawObjects(cairo_t *cc); void drawTool(Painter &painter); bool snapToPaperAndFrame(); void refreshSurface(); void computeFifi(double x, double y); virtual void invalidate() = 0; virtual void invalidate(int x, int y, int w, int h) = 0; protected: CanvasObserver *iObserver; Tool *iTool; const Page *iPage; int iPageNumber; int iView; const Cascade *iCascade; Style iStyle; Vector iPan; double iZoom; Snap iSnap; bool iDimmed; bool iAutoSnap; Vector iAutoOrigin; int iAdditionalModifiers; bool iRepaintObjects; int iWidth, iHeight; cairo_surface_t *iSurface; Vector iUnsnappedMousePos; Vector iMousePos; Vector iGlobalPos; Vector iOldFifi; // last fifi position that has been drawn bool iFifiVisible; bool iSelectionVisible; Fonts *iFonts; }; } // namespace // -------------------------------------------------------------------- #endif ipe-7.1.4/src/ipecanvas/ipecanvas.cpp0000644000175000017500000004151012120621776017374 0ustar otfriedotfried// -------------------------------------------------------------------- // ipe::Canvas // -------------------------------------------------------------------- /* This file is part of the extensible drawing editor Ipe. Copyright (C) 1993-2013 Otfried Cheong Ipe is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. As a special exception, you have permission to link Ipe with the CGAL library and distribute executables, as long as you follow the requirements of the Gnu General Public License in regard to all of the software in the executable aside from CGAL. Ipe 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 General Public License for more details. You should have received a copy of the GNU General Public License along with Ipe; if not, you can find it at "http://www.gnu.org/copyleft/gpl.html", or write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ #include "ipecanvas.h" #include "ipetool.h" #include "ipecairopainter.h" using namespace ipe; // -------------------------------------------------------------------- /*! \defgroup canvas Ipe canvas \brief A widget (control) that displays an Ipe document page. This module contains the classes needed to display and edit Ipe objects using the selected toolkit. These classes are not in Ipelib, but in a separate library libipecanvas. */ // -------------------------------------------------------------------- void CanvasObserver::canvasObserverWheelMoved(int degrees) { /* nothing */ } void CanvasObserver::canvasObserverMouseAction(int button) { /* nothing */ } void CanvasObserver::canvasObserverPositionChanged() { /* nothing */ } void CanvasObserver::canvasObserverToolChanged(bool hasTool) { /* nothing */ } void CanvasObserver::canvasObserverSizeChanged() { /* nothing */ } /*! \class ipe::Canvas \ingroup canvas \brief A widget (control) that displays an Ipe document page. */ //! Construct a new canvas. CanvasBase::CanvasBase() { iObserver = 0; iTool = 0; iPage = 0; iCascade = 0; iSurface = 0; iPan = Vector::ZERO; iZoom = 1.0; iDimmed = false; iWidth = 0; // not yet known (canvas is not yet mapped) iHeight = 0; iRepaintObjects = false; iFonts = 0; iAutoSnap = false; iFifiVisible = false; iSelectionVisible = true; iAdditionalModifiers = 0; iStyle.paperColor = Color(1000,1000,1000); iStyle.pretty = false; iStyle.classicGrid = false; iStyle.thinLine = 0.2; iStyle.thickLine = 0.9; iStyle.thinStep = 1; iStyle.thickStep = 4; iStyle.paperClip = false; iStyle.numberPages = false; iSnap.iSnap = 0; iSnap.iGridVisible = false; iSnap.iGridSize = 8; iSnap.iAngleSize = M_PI / 6.0; iSnap.iSnapDistance = 10; iSnap.iWithAxes = false; iSnap.iOrigin = Vector::ZERO; iSnap.iDir = 0; } //! destructor. CanvasBase::~CanvasBase() { if (iSurface) cairo_surface_destroy(iSurface); delete iFonts; delete iTool; ipeDebug("CanvasBase::~CanvasBase"); } // -------------------------------------------------------------------- //! set information about Latex fonts (from ipe::Document) void CanvasBase::setFontPool(const FontPool *fontPool) { delete iFonts; iFonts = Fonts::New(fontPool); } // -------------------------------------------------------------------- //! Set the page to be displayed. /*! Doesn't take ownership of any argument. The page number \a pno is only needed if page numbering is turned on. */ void CanvasBase::setPage(const Page *page, int pno, int view, const Cascade *sheet) { iPage = page; iPageNumber = pno; iView = view; iCascade = sheet; } //! Set style of canvas drawing. /*! Includes paper color, pretty text, and grid. */ void CanvasBase::setCanvasStyle(const Style &style) { iStyle = style; } //! Set current pan position. /*! The pan position is the user coordinate that is displayed at the very center of the canvas. */ void CanvasBase::setPan(const Vector &v) { iPan = v; } //! Set current zoom factor. /*! The zoom factor maps user coordinates to screen pixel coordinates. */ void CanvasBase::setZoom(double zoom) { iZoom = zoom; } //! Set the snapping information. void CanvasBase::setSnap(const Snap &s) { iSnap = s; } //! Dim whole canvas, except for the Tool. /*! This mode will be reset when the Tool finishes. */ void CanvasBase::setDimmed(bool dimmed) { iDimmed = dimmed; } //! Set additional modifiers. /*! These modifier bits are passed to the Tool when a key is pressed or a drawing action is performed in addition to the actual keyboard modifiers. */ void CanvasBase::setAdditionalModifiers(int mod) { iAdditionalModifiers = mod; } //! Enable automatic angular snapping with this origin. void CanvasBase::setAutoOrigin(const Vector &v) { iAutoOrigin = v; iAutoSnap = true; } //! Convert canvas (device) coordinates to user coordinates. Vector CanvasBase::devToUser(const Vector &arg) const { Vector v = arg - center(); v.x /= iZoom; v.y /= -iZoom; v += iPan; return v; } //! Convert user coordinates to canvas (device) coordinates. Vector CanvasBase::userToDev(const Vector &arg) const { Vector v = arg - iPan; v.x *= iZoom; v.y *= -iZoom; v += center(); return v; } //! Matrix mapping user coordinates to canvas coordinates Matrix CanvasBase::canvasTfm() const { return Matrix(center()) * Linear(iZoom, 0, 0, -iZoom) * Matrix(-iPan); } // -------------------------------------------------------------------- void CanvasBase::drawAxes(cairo_t *cc) { double alpha = 0.0; double ep = (iWidth + iHeight) / iZoom; cairo_save(cc); cairo_set_source_rgb(cc, 0.0, 1.0, 0.0); cairo_set_line_width(cc, 2.0 / iZoom); while (alpha < IpeTwoPi) { double beta = iSnap.iDir + alpha; cairo_move_to(cc, iSnap.iOrigin.x, iSnap.iOrigin.y); Vector dir(beta); cairo_rel_line_to(cc, ep * dir.x, ep * dir.y); if (alpha == 0.0) { cairo_stroke(cc); cairo_set_line_width(cc, 1.0 / iZoom); } alpha += iSnap.iAngleSize; } cairo_stroke(cc); cairo_restore(cc); } void CanvasBase::drawGrid(cairo_t *cc) { int step = iSnap.iGridSize * iStyle.thinStep; double pixstep = step * iZoom; if (pixstep < 3.0) return; // Rect paper = iCascade->findLayout()->paper(); // Vector ll = paper.bottomLeft(); // Vector ur = paper.topRight(); Vector ll = Vector::ZERO; Vector ur = iCascade->findLayout()->iFrameSize; int left = step * int(ll.x / step); if (left < ll.x) ++left; int bottom = step * int(ll.y / step); if (bottom < ll.y) ++bottom; // only draw lines that intersect canvas Vector screenUL = devToUser(Vector::ZERO); Vector screenLR = devToUser(Vector(iWidth, iHeight)); cairo_save(cc); cairo_set_source_rgb(cc, 0.3, 0.3, 0.3); if (iStyle.classicGrid) { double lw = iStyle.thinLine / iZoom; cairo_set_line_width(cc, lw); for (int y = bottom; y < ur.y; y += step) { if (screenLR.y <= y && y <= screenUL.y) { for (int x = left; x < ur.x; x += step) { if (screenUL.x <= x && x <= screenLR.x) { cairo_move_to(cc, x, y - 0.5 * lw); cairo_line_to(cc, x, y + 0.5 * lw); cairo_stroke(cc); } } } } } else { double thinLine = iStyle.thinLine / iZoom; double thickLine = iStyle.thickLine / iZoom; int thickStep = iStyle.thickStep * step; // draw horizontal lines for (int y = bottom; y < ur.y; y += step) { if (screenLR.y <= y && y <= screenUL.y) { cairo_set_line_width(cc, (y % thickStep) ? thinLine : thickLine); cairo_move_to(cc, ll.x, y); cairo_line_to(cc, ur.x, y); cairo_stroke(cc); } } // draw vertical lines for (int x = left; x < ur.x; x += step) { if (screenUL.x <= x && x <= screenLR.x) { cairo_set_line_width(cc, (x % thickStep) ? thinLine : thickLine); cairo_move_to(cc, x, ll.y); cairo_line_to(cc, x, ur.y); cairo_stroke(cc); } } } cairo_restore(cc); } void CanvasBase::drawPaper(cairo_t *cc) { const Layout *l = iCascade->findLayout(); cairo_rectangle(cc, -l->iOrigin.x, -l->iOrigin.y, l->iPaperSize.x, l->iPaperSize.y); cairo_set_source_rgb(cc, iStyle.paperColor.iRed.toDouble(), iStyle.paperColor.iGreen.toDouble(), iStyle.paperColor.iBlue.toDouble()); cairo_fill(cc); } void CanvasBase::drawFrame(cairo_t *cc) { const Layout *l = iCascade->findLayout(); cairo_set_source_rgb(cc, 0.5, 0.5, 0.5); cairo_save(cc); double dashes[2] = {3.0 / iZoom, 7.0 / iZoom}; cairo_set_dash(cc, dashes, 2, 0.0); cairo_set_line_width(cc, 2.5 / iZoom); cairo_move_to(cc, 0.0, 0.0); cairo_line_to(cc, 0.0, l->iFrameSize.y); cairo_line_to(cc, l->iFrameSize.x, l->iFrameSize.y); cairo_line_to(cc, l->iFrameSize.x, 0); cairo_close_path(cc); cairo_stroke(cc); cairo_restore(cc); } void CanvasBase::drawObjects(cairo_t *cc) { if (!iPage) return; if (iStyle.paperClip) { const Layout *l = iCascade->findLayout(); cairo_rectangle(cc, -l->iOrigin.x, -l->iOrigin.y, l->iPaperSize.x, l->iPaperSize.y); cairo_clip(cc); } CairoPainter painter(iCascade, iFonts, cc, iZoom, iStyle.pretty); painter.setDimmed(iDimmed); // painter.Transform(CanvasTfm()); painter.pushMatrix(); const Symbol *background = iCascade->findSymbol(Attribute::BACKGROUND()); if (background && iPage->findLayer("BACKGROUND") < 0) background->iObject->draw(painter); if (iStyle.numberPages) { const StyleSheet::PageNumberStyle *pns = iCascade->findPageNumberStyle(); cairo_save(cc); cairo_set_source_rgb(cc, pns->iColor.iRed.toDouble(), pns->iColor.iGreen.toDouble(), pns->iColor.iBlue.toDouble()); cairo_select_font_face(cc, "sans-serif", CAIRO_FONT_SLANT_NORMAL, CAIRO_FONT_WEIGHT_NORMAL); cairo_set_font_size(cc, pns->iFontSize); cairo_move_to(cc, pns->iPos.x, pns->iPos.y); cairo_scale(cc, 1.0, -1.0); char buf[20]; if (iPage->countViews() > 0) sprintf(buf, "%d-%d", iPageNumber + 1, iView + 1); else sprintf(buf, "%d", iPageNumber + 1); cairo_show_text(cc, buf); cairo_restore(cc); } const Text *title = iPage->titleText(); if (title) title->draw(painter); for (int i = 0; i < iPage->count(); ++i) { if (iPage->objectVisible(iView, i)) iPage->object(i)->draw(painter); } painter.popMatrix(); } // -------------------------------------------------------------------- //! Draw the current canvas tool. /*! If no tool is set, it draws the selected objects. */ void CanvasBase::drawTool(Painter &painter) { if (iTool) { iTool->draw(painter); } else if (iSelectionVisible) { for (int i = 0; i < iPage->count(); ++i) { if (iPage->objectVisible(iView, i)) { if (iPage->select(i) == EPrimarySelected) { painter.setStroke(Attribute(Color(1000, 0, 0))); painter.setPen(Attribute(Fixed(2))); iPage->object(i)->drawSimple(painter); } else if (iPage->select(i) == ESecondarySelected) { painter.setStroke(Attribute(Color(1000, 0, 1000))); painter.setPen(Attribute(Fixed(1))); iPage->object(i)->drawSimple(painter); } } } } } //! Set an observer. /*! Use 0 to delete current observer. */ void CanvasBase::setObserver(CanvasObserver *observer) { iObserver = observer; } //! Set a new tool. /*! Calls canvasObserverToolChanged(). */ void CanvasBase::setTool(Tool *tool) { assert(tool); iTool = tool; updateTool(); if (iObserver) iObserver->canvasObserverToolChanged(true); } // Current tool has done its job. /* Tool is deleted, canvas fully updated, and cursor reset. Calls canvasObserverToolChanged(). */ void CanvasBase::finishTool() { delete iTool; iTool = 0; iDimmed = false; iAutoSnap = false; update(); if (iSelectionVisible) setCursor(EStandardCursor); if (iObserver) iObserver->canvasObserverToolChanged(false); } // -------------------------------------------------------------------- bool CanvasBase::snapToPaperAndFrame() { double snapDist = iSnap.iSnapDistance / iZoom; double d = snapDist; Vector fifi = iMousePos; const Layout *layout = iCascade->findLayout(); Rect paper = layout->paper(); Rect frame(Vector::ZERO, layout->iFrameSize); // vertices if (iSnap.iSnap & Snap::ESnapVtx) { paper.bottomLeft().snap(iMousePos, fifi, d); paper.topRight().snap(iMousePos, fifi, d); paper.topLeft().snap(iMousePos, fifi, d); paper.bottomRight().snap(iMousePos, fifi, d); frame.bottomLeft().snap(iMousePos, fifi, d); frame.topRight().snap(iMousePos, fifi, d); frame.topLeft().snap(iMousePos, fifi, d); frame.bottomRight().snap(iMousePos, fifi, d); } // Return if snapping has occurred if (d < snapDist) { iMousePos = fifi; return true; } // boundary if (iSnap.iSnap & Snap::ESnapBd) { Segment(paper.bottomLeft(), paper.bottomRight()).snap(iMousePos, fifi, d); Segment(paper.bottomRight(), paper.topRight()).snap(iMousePos, fifi, d); Segment(paper.topRight(), paper.topLeft()).snap(iMousePos, fifi, d); Segment(paper.topLeft(), paper.bottomLeft()).snap(iMousePos, fifi, d); Segment(frame.bottomLeft(), frame.bottomRight()).snap(iMousePos, fifi, d); Segment(frame.bottomRight(), frame.topRight()).snap(iMousePos, fifi, d); Segment(frame.topRight(), frame.topLeft()).snap(iMousePos, fifi, d); Segment(frame.topLeft(), frame.bottomLeft()).snap(iMousePos, fifi, d); } if (d < snapDist) { iMousePos = fifi; return true; } return true; } // -------------------------------------------------------------------- //! Set whether Fifi should be shown. /*! Fifi will only be shown if a snapping mode is active. */ void CanvasBase::setFifiVisible(bool visible) { iFifiVisible = visible; if (!visible) updateTool(); // when making visible, wait for position update } //! Set whether selection should be shown when there is no tool. void CanvasBase::setSelectionVisible(bool visible) { iSelectionVisible = visible; updateTool(); } //! Return snapped mouse position without angular snapping. Vector CanvasBase::simpleSnapPos() const { Vector pos = iUnsnappedMousePos; iSnap.simpleSnap(pos, iPage, iSnap.iSnapDistance / iZoom); return pos; } // -------------------------------------------------------------------- //! Mark for update with redrawing of objects. void CanvasBase::update() { iRepaintObjects = true; invalidate(); } //! Mark for update with redrawing of tool only. void CanvasBase::updateTool() { invalidate(); } // -------------------------------------------------------------------- /*! Stores the mouse position in iUnsnappedMousePos, computes Fifi if snapping is enabled, and stores snapped position in iMousePos. */ void CanvasBase::computeFifi(double x, double y) { iUnsnappedMousePos = devToUser(Vector(x, y)); iMousePos = iUnsnappedMousePos; if (!iPage) return; int mask = iAutoSnap ? 0 : Snap::ESnapAuto; if (iSnap.iSnap & ~mask) { if (!iSnap.snap(iMousePos, iPage, iSnap.iSnapDistance / iZoom, (iAutoSnap ? &iAutoOrigin : 0))) snapToPaperAndFrame(); // convert fifi coordinates back into device space Vector fifi = userToDev(iMousePos); if (iFifiVisible && fifi != iOldFifi) { invalidate(int(iOldFifi.x - 10), int(iOldFifi.y - 10), 21, 21); invalidate(int(fifi.x - 10), int(fifi.y - 10), 21, 21); } } else if (iFifiVisible) { // remove old fifi invalidate(int(iOldFifi.x - 10), int(iOldFifi.y - 10), 21, 21); iFifiVisible = false; } } // -------------------------------------------------------------------- void CanvasBase::refreshSurface() { if (!iSurface || iWidth != cairo_image_surface_get_width(iSurface) || iHeight != cairo_image_surface_get_height(iSurface)) { // size has changed ipeDebug("size has changed to %d x %d", iWidth, iHeight); if (iSurface) cairo_surface_destroy(iSurface); iSurface = 0; iRepaintObjects = true; // give Ipe a chance to set pan and zoom according to new size if (iObserver) iObserver->canvasObserverSizeChanged(); } if (iRepaintObjects) { iRepaintObjects = false; if (!iSurface) iSurface = cairo_image_surface_create(CAIRO_FORMAT_RGB24, iWidth, iHeight); cairo_t *cc = cairo_create(iSurface); // background cairo_set_source_rgb(cc, 0.4, 0.4, 0.4); cairo_rectangle(cc, 0, 0, iWidth, iHeight); cairo_fill(cc); cairo_translate(cc, 0.5 * iWidth, 0.5 * iHeight); cairo_scale(cc, iZoom, -iZoom); cairo_translate(cc, -iPan.x, -iPan.y); if (iPage) { drawPaper(cc); if (!iStyle.pretty) drawFrame(cc); if (iSnap.iGridVisible) drawGrid(cc); drawObjects(cc); if (iSnap.iWithAxes) drawAxes(cc); } cairo_surface_flush(iSurface); cairo_destroy(cc); } } // -------------------------------------------------------------------- ipe-7.1.4/src/ipecanvas/ipecanvas_gtk.cpp0000644000175000017500000001264112120621776020244 0ustar otfriedotfried// -------------------------------------------------------------------- // ipe::Canvas for GTK // -------------------------------------------------------------------- /* This file is part of the extensible drawing editor Ipe. Copyright (C) 1993-2013 Otfried Cheong Ipe is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. As a special exception, you have permission to link Ipe with the CGAL library and distribute executables, as long as you follow the requirements of the Gnu General Public License in regard to all of the software in the executable aside from CGAL. Ipe 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 General Public License for more details. You should have received a copy of the GNU General Public License along with Ipe; if not, you can find it at "http://www.gnu.org/copyleft/gpl.html", or write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ #include "ipecanvas_gtk.h" #include "ipecairopainter.h" #include "ipetool.h" #include using namespace ipe; // -------------------------------------------------------------------- void Canvas::invalidate() { GdkRectangle r; r.x = r.y = 0; r.width = iWindow->allocation.width; r.height = iWindow->allocation.height; gdk_window_invalidate_rect(iWindow->window, &r, FALSE); } void Canvas::invalidate(int x, int y, int w, int h) { GdkRectangle r; r.x = x; r.y = y; r.width = w; r.height = h; gdk_window_invalidate_rect(iWindow->window, &r, FALSE); } // -------------------------------------------------------------------- void Canvas::buttonHandler(GdkEventButton *ev) { // ipeDebug("Canvas::button %d %d %g %g", ev->button, ev->type, ev->x, ev->y); iGlobalPos = Vector(ev->x_root, ev->y_root); computeFifi(ev->x, ev->y); // TODO: int mod = getModifiers() | iAdditionalModifiers; int mod = iAdditionalModifiers; bool down = (ev->type == GDK_BUTTON_PRESS); if (iTool) iTool->mouseButton(ev->button | mod, down); else if (down && iObserver) iObserver->canvasObserverMouseAction(ev->button | mod); } void Canvas::motionHandler(GdkEventMotion *event) { // ipeDebug("Canvas::mouseMove %g %g", event->x, event->y); computeFifi(event->x, event->y); if (iTool) iTool->mouseMove(); if (iObserver) iObserver->canvasObserverPositionChanged(); } void Canvas::scrollHandler(GdkEventScroll *event) { int zDelta = (event->direction == GDK_SCROLL_UP) ? 120 : -120; // ipeDebug("Canvas::wheel %d", zDelta); if (iObserver) iObserver->canvasObserverWheelMoved(zDelta); } void Canvas::exposeHandler(GdkEventExpose *event) { iWidth = iWindow->allocation.width; iHeight = iWindow->allocation.height; refreshSurface(); cairo_t *cr = gdk_cairo_create(iWindow->window); cairo_rectangle(cr, event->area.x, event->area.y, event->area.width, event->area.height); cairo_clip(cr); cairo_set_source_surface(cr, iSurface, 0.0, 0.0); cairo_paint(cr); if (iFifiVisible) { Vector p = userToDev(iMousePos); cairo_set_source_rgb(cr, 1.0, 0.0, 0.0); cairo_move_to(cr, p.x - 8, p.y); cairo_line_to(cr, p.x + 8, p.y); cairo_move_to(cr, p.x, p.y - 8); cairo_line_to(cr, p.x, p.y + 8); cairo_stroke(cr); iOldFifi = p; } if (iPage) { CairoPainter cp(iCascade, iFonts, cr, iZoom, false); cp.transform(canvasTfm()); cp.pushMatrix(); drawTool(cp); cp.popMatrix(); } cairo_destroy(cr); } // -------------------------------------------------------------------- gboolean Canvas::button_cb(GtkWidget *widget, GdkEvent *event, Canvas *canvas) { canvas->buttonHandler((GdkEventButton *) event); return TRUE; } gboolean Canvas::expose_cb(GtkWidget *widget, GdkEvent *event, Canvas *canvas) { canvas->exposeHandler((GdkEventExpose *) event); return TRUE; } gboolean Canvas::motion_cb(GtkWidget *widget, GdkEvent *event, Canvas *canvas) { canvas->motionHandler((GdkEventMotion *) event); return TRUE; } gboolean Canvas::scroll_cb(GtkWidget *widget, GdkEvent *event, Canvas *canvas) { canvas->scrollHandler((GdkEventScroll *) event); return TRUE; } void Canvas::setCursor(TCursor cursor, double w, Color *color) { // TODO } // -------------------------------------------------------------------- Canvas::Canvas(GtkWidget *parent) { iWindow = gtk_drawing_area_new(); gtk_widget_add_events(iWindow, GDK_BUTTON_PRESS_MASK| GDK_BUTTON_RELEASE_MASK| GDK_POINTER_MOTION_MASK); gtk_widget_set_size_request(iWindow, 600, 400); gtk_widget_set_can_focus(iWindow, TRUE); g_signal_connect(G_OBJECT(iWindow), "button-release-event", G_CALLBACK(button_cb), this); g_signal_connect(G_OBJECT(iWindow), "button-press-event", G_CALLBACK(button_cb), this); g_signal_connect(G_OBJECT(iWindow), "expose-event", G_CALLBACK(expose_cb), this); g_signal_connect(G_OBJECT(iWindow), "motion-notify-event", G_CALLBACK(motion_cb), this); g_signal_connect(G_OBJECT(iWindow), "scroll-event", G_CALLBACK(scroll_cb), this); } Canvas::~Canvas() { // do I need to delete the GTK Window? It is owned by its parent. } // -------------------------------------------------------------------- ipe-7.1.4/src/ipe/0000755000175000017500000000000012120621776013522 5ustar otfriedotfriedipe-7.1.4/src/ipe/appui_qt.cpp0000644000175000017500000005614112120621776016057 0ustar otfriedotfried// -------------------------------------------------------------------- // AppUi for QT // -------------------------------------------------------------------- /* This file is part of the extensible drawing editor Ipe. Copyright (C) 1993-2013 Otfried Cheong Ipe is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. As a special exception, you have permission to link Ipe with the CGAL library and distribute executables, as long as you follow the requirements of the Gnu General Public License in regard to all of the software in the executable aside from CGAL. Ipe 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 General Public License for more details. You should have received a copy of the GNU General Public License along with Ipe; if not, you can find it at "http://www.gnu.org/copyleft/gpl.html", or write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ #include "appui_qt.h" #include "ipecanvas_qt.h" #include "controls_qt.h" #include "ipelua.h" // for version info only #include "ipefonts.h" #include #include #include #include #include #include #include #include #include #include #include #include using namespace ipe; using namespace ipelua; // -------------------------------------------------------------------- #define SIZE 16 QIcon prefsIcon(String name) { String dir = ipeIconDirectory(); if (Platform::fileExists(dir + name + ".png")) return QIcon(QIpe(dir + name + ".png")); else return QIcon(); } QPixmap prefsPixmap(String name) { return QPixmap(QIpe(ipeIconDirectory() + name + ".png")); } QIcon prefsColorIcon(Color color) { QPixmap pixmap(SIZE, SIZE); pixmap.fill(QIpe(color)); return QIcon(pixmap); } // -------------------------------------------------------------------- IpeApp::IpeApp(lua_State *L0, int &argc, char **argv) : QApplication(argc, argv) { L = L0; } bool IpeApp::event(QEvent *event) { switch (event->type()) { case QEvent::FileOpen: loadFile(static_cast(event)->file()); return true; default: return QApplication::event(event); } } void IpeApp::loadFile(const QString &fileName) { lua_getglobal(L, "file_open_event"); lua_pushstring(L, fileName.toUtf8()); lua_call(L, 1, 0); } // -------------------------------------------------------------------- QAction *AppUi::findAction(const char *name) const { std::map::const_iterator it = iActions.find(name); if (it != iActions.end()) return it->second; else return 0; } // Not used int AppUi::actionId(const char *name) const { return 0; } void AppUi::addItem(QMenu *m, const QString &title, const char *name) { // bool canUseWhileDrawing = false; if (name[0] == '@') { // canUseWhileDrawing = true; name = name + 1; } bool checkable = (m == iMenu[EModeMenu]) || (String(name).find('|') >= 0); if (name[0] == '*') { checkable = true; name = name + 1; } QAction *a = new QAction(title, this); if (checkable) a->setCheckable(true); lua_getglobal(L, "shortcuts"); lua_getfield(L, -1, name); if (lua_isstring(L, -1)) { QString s = lua_tostring(L, -1); a->setShortcut(QKeySequence(s)); QString tt = title + " [" + s + "]"; a->setToolTip(tt); } else if (lua_istable(L, -1)) { int no = lua_rawlen(L, -1); QList kl; QString prim; for (int i = 1; i <= no; ++i) { lua_rawgeti(L, -1, i); if (lua_isstring(L, -1)) { QString s = lua_tostring(L, -1); kl.append(QKeySequence(s)); if (prim.isEmpty()) prim = s; } lua_pop(L, 1); // pop string } a->setShortcuts(kl); QString tt = title + " [" + prim + "]"; a->setToolTip(tt); } a->setIcon(prefsIcon(name)); lua_pop(L, 2); m->addAction(a); if (m == iMenu[EModeMenu]) { a->setActionGroup(iModeActionGroup); iObjectTools->addAction(a); } connect(a, SIGNAL(triggered()), iActionMap, SLOT(map())); iActionMap->setMapping(a, name); iActions[name] = a; } void AppUi::addSnap(const char *name) { QAction *a = findAction(name); assert(a); a->setCheckable(true); iSnapTools->addAction(a); } void AppUi::addEdit(const char *name) { QAction *a = findAction(name); assert(a); // a->setCheckable(true); iEditTools->addAction(a); } void AppUi::addRootMenu(int id, const char *name) { iMenu[id] = menuBar()->addMenu(name); } // if title and name == 0, add separator (default) void AppUi::addItem(int id, const char *title, const char *name) { if (title == 0) iMenu[id]->addSeparator(); else addItem(iMenu[id], QString::fromUtf8(title), name); } static QMenu *submenu = 0; static int submenuId = 0; void AppUi::startSubMenu(int id, const char *name) { submenuId = id; submenu = new QMenu(name); } void AppUi::addSubItem(const char *title, const char *name) { addItem(submenu, title, name); } MENUHANDLE AppUi::endSubMenu() { iMenu[submenuId]->addMenu(submenu); return submenu; } // -------------------------------------------------------------------- AppUi::AppUi(lua_State *L0, int model, Qt::WFlags f) : QMainWindow(0, f), AppUiBase(L0, model) { setWindowIcon(prefsIcon("ipe")); QMainWindow::setAttribute(Qt::WA_DeleteOnClose); setDockOptions(AnimatedDocks); // do not allow stacking properties and layers Canvas *canvas = new Canvas(this); iCanvas = canvas; setCentralWidget(canvas); iSnapTools = addToolBar("Snap"); iEditTools = addToolBar("Edit"); addToolBarBreak(); iObjectTools = addToolBar("Objects"); iActionMap = new QSignalMapper(this); connect(iActionMap, SIGNAL(mapped(const QString &)), SLOT(qAction(const QString &))); iModeActionGroup = new QActionGroup(this); iModeActionGroup->setExclusive(true); QActionGroup *cg = new QActionGroup(this); cg->setExclusive(true); QActionGroup *cs = new QActionGroup(this); cs->setExclusive(true); buildMenus(); findAction("coordinates|points")->setActionGroup(cg); findAction("coordinates|mm")->setActionGroup(cg); findAction("coordinates|m")->setActionGroup(cg); findAction("coordinates|inch")->setActionGroup(cg); for (uint i = 0; i < iScalings.size(); ++i) { char action[32]; sprintf(action, "scaling|%d", iScalings[i]); findAction(action)->setActionGroup(cs); } connect(iSelectLayerMenu, SIGNAL(triggered(QAction *)), SLOT(selectLayerAction(QAction *))); connect(iMoveToLayerMenu, SIGNAL(triggered(QAction *)), SLOT(moveToLayerAction(QAction *))); connect(iTextStyleMenu, SIGNAL(triggered(QAction *)), SLOT(textStyleAction(QAction *))); QSignalMapper *comboMap = new QSignalMapper(this); iSelector[EUiGridSize] = new QComboBox(); iSelector[EUiAngleSize] = new QComboBox(); iSelector[EUiGridSize]->setFocusPolicy(Qt::NoFocus); iSelector[EUiAngleSize]->setFocusPolicy(Qt::NoFocus); connect(iSelector[EUiGridSize], SIGNAL(activated(int)), comboMap, SLOT(map())); connect(iSelector[EUiAngleSize], SIGNAL(activated(int)), comboMap, SLOT(map())); comboMap->setMapping(iSelector[EUiGridSize], EUiGridSize); comboMap->setMapping(iSelector[EUiAngleSize], EUiAngleSize); addSnap("snapvtx"); addSnap("snapbd"); addSnap("snapint"); addSnap("snapgrid"); iSnapTools->addWidget(iSelector[EUiGridSize]); addSnap("snapangle"); iSnapTools->addWidget(iSelector[EUiAngleSize]); addSnap("snapauto"); addEdit("copy"); addEdit("cut"); addEdit("paste"); addEdit("delete"); addEdit("undo"); addEdit("redo"); addEdit("zoom_in"); addEdit("zoom_out"); addEdit("fit_objects"); addEdit("fit_page"); addEdit("fit_width"); addEdit("keyboard"); iShiftKey = new QAction("shift_key", this); iShiftKey->setCheckable(true); iShiftKey->setIcon(prefsIcon("shift_key")); iEditTools->addAction(iShiftKey); iEditTools->addAction(findAction("grid_visible")); connect(iShiftKey, SIGNAL(triggered()), SLOT(toolbarModifiersChanged())); iPropertiesTools = new QDockWidget("Properties", this); addDockWidget(Qt::LeftDockWidgetArea, iPropertiesTools); iPropertiesTools->setAllowedAreas(Qt::LeftDockWidgetArea| Qt::RightDockWidgetArea); iLayerTools = new QDockWidget("Layers", this); addDockWidget(Qt::LeftDockWidgetArea, iLayerTools); iLayerTools->setAllowedAreas(Qt::LeftDockWidgetArea|Qt::RightDockWidgetArea); iNotesTools = new QDockWidget("Notes", this); addDockWidget(Qt::RightDockWidgetArea, iNotesTools); iNotesTools->setAllowedAreas(Qt::LeftDockWidgetArea| Qt::RightDockWidgetArea); iMenu[EPageMenu]->addAction(iNotesTools->toggleViewAction()); iBookmarkTools = new QDockWidget("Bookmarks", this); addDockWidget(Qt::RightDockWidgetArea, iBookmarkTools); iBookmarkTools->setAllowedAreas(Qt::LeftDockWidgetArea| Qt::RightDockWidgetArea); iMenu[EPageMenu]->addAction(iBookmarkTools->toggleViewAction()); // object names are used for saving toolbar state iSnapTools->setObjectName(QLatin1String("SnapTools")); iObjectTools->setObjectName(QLatin1String("ObjectTools")); iPropertiesTools->setObjectName(QLatin1String("PropertiesTools")); iLayerTools->setObjectName(QLatin1String("LayerTools")); iNotesTools->setObjectName(QLatin1String("NotesTools")); iBookmarkTools->setObjectName(QLatin1String("BookmarkTools")); QWidget *wg = new QFrame(); QGridLayout *lo = new QGridLayout(); wg->setLayout(lo); lo->setSpacing(0); lo->setContentsMargins(0, 0, 0, 0); // wg->setMaximumWidth(150); lo->setSizeConstraint(QLayout::SetFixedSize); QButtonGroup *bg = new QButtonGroup(wg); bg->setExclusive(false); connect(bg, SIGNAL(buttonClicked(int)), this, SLOT(absoluteButton(int))); iButton[EUiMarkShape] = 0; // no such button for (int i = 0; i <= EUiSymbolSize; ++i) { if (i != EUiMarkShape) { iButton[i] = new QToolButton(); iButton[i]->setFocusPolicy(Qt::NoFocus); bg->addButton(iButton[i], i); lo->addWidget(iButton[i], i > 2 ? i+1 : i, 0); } iSelector[i] = new QComboBox(); iSelector[i]->setFocusPolicy(Qt::NoFocus); lo->addWidget(iSelector[i], i > 2 ? i+1 : i, 1); connect(iSelector[i], SIGNAL(activated(int)), comboMap, SLOT(map())); comboMap->setMapping(iSelector[i], i); } iButton[EUiStroke]->setIcon(prefsColorIcon(Color(1000, 0, 0))); iButton[EUiFill]->setIcon(prefsColorIcon(Color(1000, 1000, 0))); iButton[EUiPen]->setIcon(prefsIcon("pen")); iButton[EUiTextSize]->setIcon(prefsIcon("mode_label")); iButton[EUiSymbolSize]->setIcon(prefsIcon("mode_marks")); iButton[EUiStroke]->setToolTip("Absolute stroke color"); iButton[EUiFill]->setToolTip("Absolute fill color"); iButton[EUiPen]->setToolTip("Absolute pen width"); iButton[EUiTextSize]->setToolTip("Absolute text size"); iButton[EUiSymbolSize]->setToolTip("Absolute symbol size"); iSelector[EUiStroke]->setToolTip("Symbolic stroke color"); iSelector[EUiFill]->setToolTip("Symbolic fill color"); iSelector[EUiPen]->setToolTip("Symbolic pen width"); iSelector[EUiTextSize]->setToolTip("Symbolic text size"); iSelector[EUiMarkShape]->setToolTip("Mark shape"); iSelector[EUiSymbolSize]->setToolTip("Symbolic symbol size"); iSelector[EUiGridSize]->setToolTip("Grid size"); iSelector[EUiAngleSize]->setToolTip("Angle for angular snap"); connect(comboMap, SIGNAL(mapped(int)), this, SLOT(comboSelector(int))); QLabel *msl = new QLabel(); msl->setPixmap(prefsPixmap("mode_marks")); lo->addWidget(msl, EUiMarkShape + 1, 0); iPathView = new PathView(); connect(iPathView, SIGNAL(activated(String)), SLOT(action(String))); connect(iPathView, SIGNAL(showPathStylePopup(Vector)), SLOT(showPathStylePopup(Vector))); lo->addWidget(iPathView, 3, 0, 1, 2); // lo->setRowStretch(3, 1); iPropertiesTools->setWidget(wg); QHBoxLayout *hol = new QHBoxLayout(); iViewNumber = new QToolButton(); iPageNumber = new QToolButton(); iViewNumber->setFocusPolicy(Qt::NoFocus); iPageNumber->setFocusPolicy(Qt::NoFocus); iViewNumber->setText("View 1/1"); iViewNumber->setToolTip("Current view number"); iPageNumber->setText("Page 1/1"); iPageNumber->setToolTip("Current page number"); iViewMarked = new QCheckBox(); iPageMarked = new QCheckBox(); iViewMarked->setFocusPolicy(Qt::NoFocus); iPageMarked->setFocusPolicy(Qt::NoFocus); bg->addButton(iViewNumber, EUiView); bg->addButton(iPageNumber, EUiPage); bg->addButton(iViewMarked, EUiViewMarked); bg->addButton(iPageMarked, EUiPageMarked); hol->setSpacing(0); hol->addWidget(iViewMarked); hol->addWidget(iViewNumber); hol->addStretch(1); hol->addWidget(iPageMarked); hol->addWidget(iPageNumber); lo->addLayout(hol, EUiSymbolSize + 2, 0, 1, -1); iPageNotes = new QTextEdit(); iPageNotes->setAcceptRichText(false); iPageNotes->setReadOnly(true); iPageNotes->setFocusPolicy(Qt::NoFocus); iNotesTools->setWidget(iPageNotes); iBookmarks = new QListWidget(); iBookmarks->setToolTip("Bookmarks of this document"); iBookmarks->setFocusPolicy(Qt::NoFocus); connect(iBookmarks, SIGNAL(itemActivated(QListWidgetItem *)), this, SLOT(bookmarkSelected(QListWidgetItem *))); iBookmarkTools->setWidget(iBookmarks); iLayerList = new LayerBox(); iLayerList->setToolTip("Layers of this page"); iLayerTools->setWidget(iLayerList); connect(iLayerList, SIGNAL(activated(String, String)), this, SLOT(layerAction(String, String))); connect(iLayerList, SIGNAL(showLayerBoxPopup(Vector, String)), SLOT(showLayerBoxPopup(Vector, String))); connect(iSelectLayerMenu, SIGNAL(aboutToShow()), this, SLOT(aboutToShowSelectLayerMenu())); connect(iMoveToLayerMenu, SIGNAL(aboutToShow()), this, SLOT(aboutToShowMoveToLayerMenu())); connect(iTextStyleMenu, SIGNAL(aboutToShow()), this, SLOT(aboutToShowTextStyleMenu())); iMouse = new QLabel(statusBar()); findAction("coordinates|points")->setChecked(true); statusBar()->addPermanentWidget(iMouse, 0); QFont font = iMouse->font(); font.setFamily("Monospace"); iMouse->setFont(font); iResolution = new QLabel(statusBar()); statusBar()->addPermanentWidget(iResolution, 0); iCanvas->setObserver(this); } AppUi::~AppUi() { ipeDebug("AppUi C++ destructor"); } // -------------------------------------------------------------------- void AppUi::aboutToShowSelectLayerMenu() { iSelectLayerMenu->clear(); for (int i = 0; i < iLayerList->count(); ++i) { QAction *a = new QAction(iLayerList->item(i)->text(), iSelectLayerMenu); iSelectLayerMenu->addAction(a); } } void AppUi::selectLayerAction(QAction *a) { action(String("selectinlayer-") + IpeQ(a->text())); } void AppUi::aboutToShowMoveToLayerMenu() { iMoveToLayerMenu->clear(); for (int i = 0; i < iLayerList->count(); ++i) { QAction *a = new QAction(iLayerList->item(i)->text(), iMoveToLayerMenu); iMoveToLayerMenu->addAction(a); } } void AppUi::moveToLayerAction(QAction *a) { action(String("movetolayer-") + IpeQ(a->text())); } void AppUi::aboutToShowTextStyleMenu() { AttributeSeq seq; iCascade->allNames(ETextStyle, seq); iTextStyleMenu->clear(); for (uint i = 0; i < seq.size(); ++i) { String s = seq[i].string(); QAction *a = new QAction(QIpe(s), iTextStyleMenu); a->setCheckable(true); if (s == iAll.iTextStyle.string()) a->setChecked(true); iTextStyleMenu->addAction(a); } } void AppUi::textStyleAction(QAction *a) { action(String("textstyle|") + IpeQ(a->text())); } void AppUi::toolbarModifiersChanged() { if (iCanvas) { int mod = 0; if (iShiftKey->isChecked()) mod |= CanvasBase::EShift; iCanvas->setAdditionalModifiers(mod); } } // -------------------------------------------------------------------- void AppUi::resetCombos() { for (int i = 0; i < EUiView; ++i) iSelector[i]->clear(); } void AppUi::addComboColor(int sel, String s, Color color) { QIcon icon = prefsColorIcon(color); iSelector[sel]->addItem(icon, QIpe(s)); } void AppUi::addCombo(int sel, String s) { iSelector[sel]->addItem(QIpe(s)); } void AppUi::setComboCurrent(int sel, int idx) { iSelector[sel]->setCurrentIndex(idx); } void AppUi::setButtonColor(int sel, Color color) { iButton[sel]->setIcon(prefsColorIcon(color)); } void AppUi::setPathView(const AllAttributes &all, Cascade *sheet) { iPathView->set(all, sheet); } void AppUi::setCheckMark(String name, Attribute a) { String sa = name + "|"; int na = sa.size(); String sb = sa + a.string(); for (std::map::iterator it = iActions.begin(); it != iActions.end(); ++it) { if (it->first.left(na) == sa) it->second->setChecked(it->first == sb); } } void AppUi::setNumbers(String vno, bool vm, String pno, bool pm) { if (vno.isEmpty()) { iViewNumber->hide(); iViewMarked->hide(); } else { iViewNumber->setText(QIpe(vno)); iViewNumber->show(); iViewMarked->setCheckState(vm ? Qt::Checked : Qt::Unchecked); iViewMarked->show(); } if (pno.isEmpty()) { iPageNumber->hide(); iPageMarked->hide(); } else { iPageNumber->show(); iPageMarked->show(); iPageNumber->setText(QIpe(pno)); iPageMarked->setCheckState(pm ? Qt::Checked : Qt::Unchecked); } } void AppUi::setNotes(String notes) { iPageNotes->setPlainText(QIpe(notes)); } void AppUi::setLayers(const Page *page, int view) { iLayerList->set(page, view); } void AppUi::setBookmarks(int no, const String *s) { iBookmarks->clear(); for (int i = 0; i < no; ++i) { QListWidgetItem *item = new QListWidgetItem(QIpe(s[i])); if (s[i][0] == ' ') item->setTextColor(Qt::blue); iBookmarks->addItem(item); } } void AppUi::bookmarkSelected(QListWidgetItem *item) { int index = iBookmarks->row(item); luaBookmarkSelected(index); } void AppUi::setToolVisible(int m, bool vis) { QWidget *tool = 0; switch (m) { case 0: tool = iPropertiesTools; break; case 1: tool = iBookmarkTools; break; case 2: tool = iNotesTools; break; case 3: tool = iLayerTools; break; default: break; } if (vis) tool->show(); else tool->hide(); } void AppUi::setZoom(double zoom) { QString s; s.sprintf("(%dppi)", int(72.0 * zoom)); iResolution->setText(s); iCanvas->setZoom(zoom); } // -------------------------------------------------------------------- static void enableActions(QMenu *menu, bool mode) { menu->setEnabled(mode); QListIterator it(menu->actions()); while (it.hasNext()) it.next()->setEnabled(mode); } void AppUi::setActionsEnabled(bool mode) { enableActions(iMenu[EFileMenu], mode); enableActions(iMenu[EEditMenu], mode); enableActions(iMenu[EModeMenu], mode); enableActions(iMenu[EPropertiesMenu], mode); enableActions(iMenu[ELayerMenu], mode); enableActions(iMenu[EViewMenu], mode); enableActions(iMenu[EPageMenu], mode); enableActions(iMenu[EIpeletMenu], mode); iModeActionGroup->setEnabled(mode); iPropertiesTools->setEnabled(mode); iLayerTools->setEnabled(mode); iBookmarkTools->setEnabled(mode); } // -------------------------------------------------------------------- //! Window has been closed void AppUi::closeEvent(QCloseEvent* ce) { // calls model lua_rawgeti(L, LUA_REGISTRYINDEX, iModel); lua_getfield(L, -1, "closeEvent"); lua_pushvalue(L, -2); // model lua_remove(L, -3); lua_call(L, 1, 1); bool result = lua_toboolean(L, -1); if (result) ce->accept(); else ce->ignore(); } // -------------------------------------------------------------------- // Determine if action is checked // Used for snapXXX, grid_visible, viewmarked, and pagemarked bool AppUi::actionState(const char *name) { if (!strcmp(name, "viewmarked")) return (iViewMarked->checkState() == Qt::Checked); if (!strcmp(name, "pagemarked")) return (iPageMarked->checkState() == Qt::Checked); QAction *a = findAction(name); if (a) return a->isChecked(); else return 0; } // Check/uncheck an action // Used for snapXXX, grid_visible, to initialize mode_select void AppUi::setActionState(const char *name, bool value) { QAction *a = findAction(name); if (a) a->setChecked(value); } void AppUi::absoluteButton(int id) { luaAbsoluteButton(selectorNames[id]); } void AppUi::selector(int id, String value) { luaSelector(String(selectorNames[id]), value); } void AppUi::comboSelector(int id) { luaSelector(String(selectorNames[id]), IpeQ(iSelector[id]->currentText())); } // -------------------------------------------------------------------- static const char * const aboutText = "

Ipe %d.%d.%d

" "

Copyright (c) 1993-2013 Otfried Cheong

" "

The extensible drawing editor Ipe creates figures " "in Postscript and PDF format, " "using LaTeX to format the text in the figures.

" "

Ipe relies on the following fine pieces of software:" "

    " "
  • Pdflatex" "
  • %s (%d kB used)" // Lua "
  • The font rendering library %s" "
  • The rendering library Cairo %s / %s" "
  • The GUI toolkit Qt %s / %s" "
  • The compression library zlib %s" "
  • Some code from Xpdf" "
" "

Ipe is released under the GNU Public License.

" "

See ipe7.sourceforge.net" " for details.

" "
"; void AppUi::aboutIpe() { int luaSize = lua_gc(L, LUA_GCCOUNT, 0); std::vector buf(strlen(aboutText) + 100); sprintf(&buf[0], aboutText, IPELIB_VERSION / 10000, (IPELIB_VERSION / 100) % 100, IPELIB_VERSION % 100, LUA_RELEASE, luaSize, Fonts::freetypeVersion().z(), CAIRO_VERSION_STRING, cairo_version_string(), QT_VERSION_STR, qVersion(), ZLIB_VERSION); QMessageBox msgBox(this); msgBox.setWindowTitle("About Ipe"); msgBox.setWindowIcon(prefsIcon("ipe")); msgBox.setInformativeText(&buf[0]); msgBox.setIconPixmap(prefsPixmap("ipe")); msgBox.setStandardButtons(QMessageBox::Ok); msgBox.exec(); } void AppUi::qAction(const QString &name) { action(IpeQ(name)); } void AppUi::action(String name) { if (name == "fullscreen") { setWindowState(windowState() ^ Qt::WindowFullScreen); } else if (name == "about") { aboutIpe(); } else luaAction(name); } // -------------------------------------------------------------------- void AppUi::showPathStylePopup(Vector v) { luaShowPathStylePopup(v); } void AppUi::showLayerBoxPopup(Vector v, String layer) { luaShowLayerBoxPopup(v, layer); } void AppUi::layerAction(String name, String layer) { luaLayerAction(name, layer); } // -------------------------------------------------------------------- WINID AppUi::windowId() { return this; } void AppUi::closeWindow() { close(); } void AppUi::setWindowCaption(bool mod, const char *s) { setWindowModified(mod); setWindowTitle(QString::fromUtf8(s)); } void AppUi::setMouseIndicator(const char *s) { iMouse->setText(s); } void AppUi::explain(const char *s, int t) { statusBar()->showMessage(QString::fromUtf8(s), t); } void AppUi::showWindow(int width, int height) { if (width > 0 && height > 0) resize(width, height); show(); } AppUiBase *createAppUi(lua_State *L0, int model) { return new AppUi(L0, model); } // -------------------------------------------------------------------- ipe-7.1.4/src/ipe/appui_gtk.cpp0000644000175000017500000002350012120621776016211 0ustar otfriedotfried// -------------------------------------------------------------------- // AppUi for GTK // -------------------------------------------------------------------- /* This file is part of the extensible drawing editor Ipe. Copyright (C) 1993-2013 Otfried Cheong Ipe is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. As a special exception, you have permission to link Ipe with the CGAL library and distribute executables, as long as you follow the requirements of the Gnu General Public License in regard to all of the software in the executable aside from CGAL. Ipe 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 General Public License for more details. You should have received a copy of the GNU General Public License along with Ipe; if not, you can find it at "http://www.gnu.org/copyleft/gpl.html", or write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ #include "appui_gtk.h" #include "ipecanvas_gtk.h" // #include "controls_qt.h" #include "ipelua.h" // for version info only #include "ipefonts.h" #include #include #include using namespace ipe; using namespace ipelua; // -------------------------------------------------------------------- #if 0 QIcon prefsIcon(String name) { String dir = ipeIconDirectory(); if (Platform::fileExists(dir + name + ".png")) return QIcon(QIpe(dir + name + ".png")); else return QIcon(); } QPixmap prefsPixmap(String name) { return QPixmap(QIpe(ipeIconDirectory() + name + ".png")); } QIcon prefsColorIcon(Color color) { QPixmap pixmap(SIZE, SIZE); pixmap.fill(QIpe(color)); return QIcon(pixmap); } #endif // -------------------------------------------------------------------- #if 0 QAction *AppUi::findAction(const char *name) const { std::map::const_iterator it = iActions.find(name); if (it != iActions.end()) return it->second; else return 0; } void AppUi::addItem(QMenu *m, const QString &title, const char *name) { QAction *a = new QAction(title, this); lua_getglobal(L, "shortcuts"); lua_getfield(L, -1, name); if (lua_isstring(L, -1)) { QString s = lua_tostring(L, -1); a->setShortcut(QKeySequence(s)); QString tt = title + " [" + s + "]"; a->setToolTip(tt); } else if (lua_istable(L, -1)) { int no = lua_objlen(L, -1); QList kl; QString prim; for (int i = 1; i <= no; ++i) { lua_rawgeti(L, -1, i); if (lua_isstring(L, -1)) { QString s = lua_tostring(L, -1); kl.append(QKeySequence(s)); if (prim.isEmpty()) prim = s; } lua_pop(L, 1); // pop string } a->setShortcuts(kl); QString tt = title + " [" + prim + "]"; a->setToolTip(tt); } a->setIcon(prefsIcon(name)); lua_pop(L, 2); m->addAction(a); if (m == iMenu[EModeMenu]) { a->setCheckable(true); a->setActionGroup(iModeActionGroup); iObjectTools->addAction(a); } if (String(name).find('|') >= 0) { // selector item a->setCheckable(true); } connect(a, SIGNAL(triggered()), iActionMap, SLOT(map())); iActionMap->setMapping(a, name); iActions[name] = a; } #endif static String change_mnemonic(const char *s) { int n = strlen(s); String r; int i = 0; while (i < n) { if (s[i] == '&') { if (i+1 < n && s[i+1] == '&') { r += '&'; ++i; // extra } else r += '_'; } else r += s[i]; ++i; } return r; } void AppUi::addRootMenu(int id, const char *name) { iRootMenu[id] = gtk_menu_item_new_with_mnemonic(change_mnemonic(name).z()); iSubMenu[id] = gtk_menu_new(); } void AppUi::menuitem_cb(GtkWidget *item, gpointer data) { AppUi *ui = (AppUi *) g_object_get_data(G_OBJECT(item), "ipe-appui"); gint idx = GPOINTER_TO_INT(data); ui->action(ui->iActions[idx].name); } void AppUi::addItem(GtkMenuShell *shell, const char *title, const char *name) { if (!title) { GtkWidget *item = gtk_separator_menu_item_new(); gtk_menu_shell_append(shell, item); gtk_widget_show(item); return; } bool checkable = (shell == GTK_MENU_SHELL(iSubMenu[EModeMenu]) || String(name).find('|') >= 0); if (name[0] == '*') { checkable = true; name = name + 1; } GtkWidget *item = checkable ? gtk_check_menu_item_new_with_mnemonic(change_mnemonic(title).z()) : gtk_menu_item_new_with_mnemonic(change_mnemonic(title).z()); SAction s; s.name = String(name); s.menuItem = item; iActions.push_back(s); g_object_set_data(G_OBJECT(item), "ipe-appui", this); gtk_menu_shell_append(shell, item); g_signal_connect(item, "activate", G_CALLBACK(menuitem_cb), GINT_TO_POINTER(iActions.size() - 1)); gtk_widget_show(item); } void AppUi::addItem(int id, const char *title, const char *name) { GtkMenuShell *shell = GTK_MENU_SHELL(iSubMenu[id]); addItem(shell, title, name); } static GtkWidget *submenu = 0; static GtkWidget *submenuitem = 0; static int submenuId = 0; void AppUi::startSubMenu(int id, const char *name) { submenuId = id; submenu = gtk_menu_new(); submenuitem = gtk_menu_item_new_with_mnemonic(change_mnemonic(name).z()); } void AppUi::addSubItem(const char *title, const char *name) { GtkMenuShell *shell = GTK_MENU_SHELL(submenu); addItem(shell, title, name); } MENUHANDLE AppUi::endSubMenu() { gtk_menu_item_set_submenu(GTK_MENU_ITEM(submenuitem), submenu); gtk_widget_show(submenuitem); GtkMenuShell *menu = GTK_MENU_SHELL(iSubMenu[submenuId]); gtk_menu_shell_append(menu, submenuitem); return GTK_MENU(submenu); } // -------------------------------------------------------------------- AppUi::AppUi(lua_State *L0, int model) : AppUiBase(L0, model) { iWindow = gtk_window_new(GTK_WINDOW_TOPLEVEL); // gtk_widget_set_size_request (GTK_WIDGET(iWindow), 600, 400); g_signal_connect(iWindow, "delete-event", G_CALLBACK(gtk_main_quit), NULL); iAccelGroup = gtk_accel_group_new(); gtk_window_add_accel_group(GTK_WINDOW(iWindow), iAccelGroup); buildMenus(); GtkWidget *menu_bar = gtk_menu_bar_new(); GtkWidget *vbox = gtk_vbox_new(FALSE, 0); gtk_container_add(GTK_CONTAINER(iWindow), vbox); gtk_widget_show(vbox); gtk_box_pack_start(GTK_BOX(vbox), menu_bar, FALSE, FALSE, 0); gtk_widget_show(menu_bar); for (int i = 0; i < ENumMenu; ++i) { gtk_widget_show(iRootMenu[i]); gtk_menu_item_set_submenu(GTK_MENU_ITEM(iRootMenu[i]), iSubMenu[i]); gtk_menu_shell_append(GTK_MENU_SHELL(menu_bar), iRootMenu[i]); } Canvas *canvas = new Canvas(iWindow); gtk_box_pack_start(GTK_BOX(vbox), canvas->window(), TRUE, TRUE, 0); gtk_widget_show(canvas->window()); iCanvas = canvas; iCanvas->setObserver(this); iStatusBar = gtk_statusbar_new(); iStatusBarContextid = gtk_statusbar_get_context_id(GTK_STATUSBAR(iStatusBar), "explain"); iMousePosition = gtk_label_new(0); iResolution = gtk_label_new(0); GtkBox *sb = GTK_BOX(gtk_statusbar_get_message_area(GTK_STATUSBAR(iStatusBar))); gtk_box_pack_end(sb, iResolution, FALSE, FALSE, 0); gtk_box_pack_end(sb, iMousePosition, FALSE, FALSE, 0); gtk_widget_show(iResolution); gtk_widget_show(iMousePosition); gtk_box_pack_end(GTK_BOX(vbox), iStatusBar, FALSE, FALSE, 0); gtk_widget_show(iStatusBar); } AppUi::~AppUi() { ipeDebug("AppUi C++ destructor"); // TODO: destroy iWindow or not? } // -------------------------------------------------------------------- void AppUi::setupSymbolicNames(const Cascade *sheet) { } void AppUi::setAttributes(const AllAttributes &all, Cascade *sheet) { } void AppUi::setGridAngleSize(Attribute abs_grid, Attribute abs_angle) { } void AppUi::setLayers(const Page *page, int view) { } void AppUi::setZoom(double zoom) { char s[32]; sprintf(s, "(%dppi)", int(72.0 * zoom)); iCanvas->setZoom(zoom); gtk_label_set_text(GTK_LABEL(iResolution), s); } void AppUi::setActionsEnabled(bool mode) { } void AppUi::setNumbers(String vno, bool vm, String pno, bool pm) { } void AppUi::setNotes(String notes) { } bool AppUi::checkbox(lua_State *L) { return false; } int AppUi::actionId(const char *name) { for (int i = 0; i < int(iActions.size()); ++i) { if (iActions[i].name == name) return i; } return -1; } // only used for snapXXX and grid_size bool AppUi::actionState(const char *name) { int idx = actionId(name); return (idx >= 0) ? gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM(iActions[idx].menuItem)) : false; } // only used for snapXXX and grid_size void AppUi::setActionState(const char *name, bool value) { int idx = actionId(name); if (idx >= 0) gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(iActions[idx].menuItem), value); } int AppUi::setBookmarks(lua_State *L) { return 0; } int AppUi::showTool(lua_State *L) { return 0; } // -------------------------------------------------------------------- WINID AppUi::windowId() { return iWindow; } bool AppUi::closeWindow() { delete this; return false; } void AppUi::explain(const char *s, int t) { gtk_statusbar_push(GTK_STATUSBAR(iStatusBar), iStatusBarContextid, s); } void AppUi::setWindowCaption(const char *s) { gtk_window_set_title(GTK_WINDOW(iWindow), s); } void AppUi::setMouseIndicator(const char *s) { gtk_label_set_text(GTK_LABEL(iMousePosition), s); } void AppUi::showWindow(int width, int height) { gtk_widget_show(iWindow); } // -------------------------------------------------------------------- void AppUi::action(String name) { ipeDebug("action %s", name.z()); luaAction(name); } AppUiBase *createAppUi(lua_State *L0, int model) { return new AppUi(L0, model); } // -------------------------------------------------------------------- ipe-7.1.4/src/ipe/appui_qt.h0000644000175000017500000001242012120621776015514 0ustar otfriedotfried// -*- C++ -*- // -------------------------------------------------------------------- // Appui for QT // -------------------------------------------------------------------- /* This file is part of the extensible drawing editor Ipe. Copyright (C) 1993-2013 Otfried Cheong Ipe is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. As a special exception, you have permission to link Ipe with the CGAL library and distribute executables, as long as you follow the requirements of the Gnu General Public License in regard to all of the software in the executable aside from CGAL. Ipe 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 General Public License for more details. You should have received a copy of the GNU General Public License along with Ipe; if not, you can find it at "http://www.gnu.org/copyleft/gpl.html", or write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ #ifndef APPUI_QT_H #define APPUI_QT_H #include "appui.h" #include #include #include #include #include #include #include #include #include #include #include #include using namespace ipe; // -------------------------------------------------------------------- class PathView; class LayerBox; class QSignalMapper; // -------------------------------------------------------------------- class IpeApp : public QApplication { Q_OBJECT public: IpeApp(lua_State *L0, int &argc, char **argv); protected: virtual bool event(QEvent *); private: void loadFile(const QString &fileName); lua_State *L; }; // -------------------------------------------------------------------- class AppUi : public QMainWindow, public AppUiBase { Q_OBJECT public: AppUi(lua_State *L0, int model, Qt::WFlags f=0); ~AppUi(); QAction *findAction(const char *name) const; virtual void setLayers(const Page *page, int view); virtual void setZoom(double zoom); virtual void setActionsEnabled(bool mode); virtual void setNumbers(String vno, bool vm, String pno, bool pm); virtual void setNotes(String notes); virtual int actionId(const char *name) const; virtual WINID windowId(); virtual void closeWindow(); virtual bool actionState(const char *name); virtual void setActionState(const char *name, bool value); virtual void setWindowCaption(bool mod, const char *s); virtual void explain(const char *s, int t); virtual void showWindow(int width, int height); virtual void setBookmarks(int no, const String *s); virtual void setToolVisible(int m, bool vis); public slots: void action(String name); void qAction(const QString &name); void selectLayerAction(QAction *a); void moveToLayerAction(QAction *a); void textStyleAction(QAction *a); void layerAction(String name, String layer); void toolbarModifiersChanged(); void aboutIpe(); void absoluteButton(int id); void selector(int id, String value); void comboSelector(int id); void bookmarkSelected(QListWidgetItem *item); void aboutToShowSelectLayerMenu(); void aboutToShowMoveToLayerMenu(); void aboutToShowTextStyleMenu(); void showPathStylePopup(Vector v); void showLayerBoxPopup(Vector v, String layer); private: void addItem(QMenu *m, const QString &title, const char *name); void addItem(int m, const QString &title, const char *name); void addSnap(const char *name); void addEdit(const char *name); private: virtual void addRootMenu(int id, const char *name); virtual void addItem(int id, const char *title, const char *name); virtual void startSubMenu(int id, const char *name); virtual void addSubItem(const char *title, const char *name); virtual MENUHANDLE endSubMenu(); virtual void setMouseIndicator(const char *s); virtual void addCombo(int sel, String s); virtual void resetCombos(); virtual void addComboColor(int sel, String s, Color color); virtual void setComboCurrent(int sel, int idx); virtual void setCheckMark(String name, Attribute a); virtual void setPathView(const AllAttributes &all, Cascade *sheet); virtual void setButtonColor(int sel, Color color); protected: void closeEvent(QCloseEvent *ev); private: PathView *iPathView; QMenu *iMenu[ENumMenu]; QToolButton *iButton[EUiGridSize]; QComboBox *iSelector[EUiView]; QToolButton *iViewNumber; QToolButton *iPageNumber; QCheckBox *iViewMarked; QCheckBox *iPageMarked; QToolBar *iSnapTools; QToolBar *iEditTools; QToolBar *iObjectTools; QDockWidget *iPropertiesTools; QDockWidget *iLayerTools; QDockWidget *iBookmarkTools; QDockWidget *iNotesTools; QActionGroup *iModeActionGroup; QAction *iShiftKey; QListWidget *iBookmarks; LayerBox *iLayerList; QTextEdit *iPageNotes; QLabel *iMouse; QLabel *iResolution; QSignalMapper *iActionMap; std::map iActions; }; // -------------------------------------------------------------------- #endif ipe-7.1.4/src/ipe/ipe.rc0000644000175000017500000000152712120621776014632 0ustar otfriedotfried#include #define IDI_MYICON 1 IDI_MYICON ICON DISCARDABLE "ipe.ico" VS_VERSION_INFO VERSIONINFO FILEVERSION 7,1,4,1 PRODUCTVERSION 7,1,4,1 FILEFLAGSMASK VS_FF_PRERELEASE FILEFLAGS VS_FF_PRERELEASE FILEOS VOS__WINDOWS32 FILETYPE VFT_APP FILESUBTYPE 0x0L BEGIN BLOCK "StringFileInfo" BEGIN BLOCK "040904B0" BEGIN VALUE "CompanyName", "Otfried Cheong\0" VALUE "FileDescription", "Ipe drawing editor\0" VALUE "FileVersion", "7, 1, 4, 1\0" VALUE "InternalName", "Ipe\0" VALUE "LegalCopyright", "Copyright (C) 2013\0" VALUE "LegalTrademarks", "\0" VALUE "OriginalFilename", "Ipe.exe\0" VALUE "ProductName", "Ipe\0" VALUE "ProductVersion", "7, 1, 4, 1\0" END END END // CREATEPROCESS_MANIFEST_RESOURCE_ID RT_MANIFEST "ipe.exe.manifest" ipe-7.1.4/src/ipe/uilua.cpp0000644000175000017500000005462412120621776015360 0ustar otfriedotfried// -------------------------------------------------------------------- // Lua bindings for user interface // -------------------------------------------------------------------- /* This file is part of the extensible drawing editor Ipe. Copyright (C) 1993-2013 Otfried Cheong Ipe is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. As a special exception, you have permission to link Ipe with the CGAL library and distribute executables, as long as you follow the requirements of the Gnu General Public License in regard to all of the software in the executable aside from CGAL. Ipe 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 General Public License for more details. You should have received a copy of the GNU General Public License along with Ipe; if not, you can find it at "http://www.gnu.org/copyleft/gpl.html", or write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ #include "appui.h" #include "ipecanvas.h" #include "tools.h" #include "ipelua.h" #include #include #ifdef IPEUI_QT #include "ipeselector_qt.h" #include "controls_qt.h" #include #include #include #include #include #include #endif using namespace ipe; using namespace ipelua; // -------------------------------------------------------------------- static CanvasBase *check_canvas(lua_State *L, int i) { AppUiBase **ui = (AppUiBase **) luaL_checkudata(L, i, "Ipe.appui"); return (*ui)->canvas(); } inline AppUiBase **check_appui(lua_State *L, int i) { return (AppUiBase **) luaL_checkudata(L, i, "Ipe.appui"); } static int appui_tostring(lua_State *L) { check_appui(L, 1); lua_pushfstring(L, "AppUi@%p", lua_topointer(L, 1)); return 1; } /* When the Lua model is collected, its "ui" userdata will be garbage collected as well. At this point, the C++ object has long been deleted. */ static int appui_destructor(lua_State *L) { check_appui(L, 1); ipeDebug("AppUi Lua destructor"); return 0; } // -------------------------------------------------------------------- static int appui_setPage(lua_State *L) { AppUiBase **ui = check_appui(L, 1); Page *page = check_page(L, 2)->page; int pno = luaL_checkinteger(L, 3) - 1; int view = check_viewno(L, 4, page); Cascade *sheets = check_cascade(L, 5)->cascade; (*ui)->canvas()->setPage(page, pno, view, sheets); return 0; } static int appui_setFontPool(lua_State *L) { CanvasBase *canvas = check_canvas(L, 1); Document **d = check_document(L, 2); const FontPool *fonts = (*d)->fontPool(); canvas->setFontPool(fonts); return 0; } static int appui_pan(lua_State *L) { CanvasBase *canvas = check_canvas(L, 1); Vector p = canvas->pan(); push_vector(L, p); return 1; } static int appui_setPan(lua_State *L) { CanvasBase *canvas = check_canvas(L, 1); Vector *v = check_vector(L, 2); canvas->setPan(*v); return 0; } static int appui_zoom(lua_State *L) { CanvasBase *canvas = check_canvas(L, 1); lua_pushnumber(L, canvas->zoom()); return 1; } static int appui_setZoom(lua_State *L) { AppUiBase **ui = check_appui(L, 1); (*ui)->setZoom(luaL_checknumber(L, 2)); return 0; } static int appui_pos(lua_State *L) { CanvasBase *canvas = check_canvas(L, 1); push_vector(L, canvas->pos()); return 1; } static int appui_globalPos(lua_State *L) { CanvasBase *canvas = check_canvas(L, 1); push_vector(L, canvas->globalPos()); return 1; } static int appui_unsnappedPos(lua_State *L) { CanvasBase *canvas = check_canvas(L, 1); push_vector(L, canvas->unsnappedPos()); return 1; } static int appui_simpleSnapPos(lua_State *L) { CanvasBase *canvas = check_canvas(L, 1); push_vector(L, canvas->simpleSnapPos()); return 1; } static int appui_setFifiVisible(lua_State *L) { CanvasBase *canvas = check_canvas(L, 1); canvas->setFifiVisible(lua_toboolean(L, 2)); return 0; } static int appui_setSelectionVisible(lua_State *L) { CanvasBase *canvas = check_canvas(L, 1); canvas->setSelectionVisible(lua_toboolean(L, 2)); return 0; } static void snapFlag(lua_State *L, int &flags, const char *mode, uint bits) { lua_getfield(L, -1, mode); if (!lua_isnil(L, -1)) flags = lua_toboolean(L, -1) ? (flags | bits) : (flags & ~bits); lua_pop(L, 1); } static int appui_setSnap(lua_State *L) { CanvasBase *canvas = check_canvas(L, 1); luaL_checktype(L, 2, LUA_TTABLE); Snap snap = canvas->snap(); snapFlag(L, snap.iSnap, "snapvtx", Snap::ESnapVtx); snapFlag(L, snap.iSnap, "snapbd", Snap::ESnapBd); snapFlag(L, snap.iSnap, "snapint", Snap::ESnapInt); snapFlag(L, snap.iSnap, "snapgrid", Snap::ESnapGrid); snapFlag(L, snap.iSnap, "snapangle", Snap::ESnapAngle); snapFlag(L, snap.iSnap, "snapauto", Snap::ESnapAuto); lua_getfield(L, -1, "grid_visible"); if (!lua_isnil(L, -1)) snap.iGridVisible = lua_toboolean(L, -1); lua_pop(L, 1); lua_getfield(L, -1, "gridsize"); if (!lua_isnil(L, -1)) snap.iGridSize = luaL_checkint(L, -1); lua_pop(L, 1); lua_getfield(L, -1, "anglesize"); if (!lua_isnil(L, -1)) snap.iAngleSize = IpePi * luaL_checknumber(L, -1) / 180.0; lua_pop(L, 1); lua_getfield(L, -1, "snap_distance"); if (!lua_isnil(L, -1)) snap.iSnapDistance = luaL_checkint(L, -1); lua_pop(L, 1); lua_getfield(L, -1, "with_axes"); if (!lua_isnil(L, -1)) snap.iWithAxes = lua_toboolean(L, -1); lua_pop(L, 1); lua_getfield(L, -1, "origin"); if (is_type(L, -1, "Ipe.vector")) snap.iOrigin = *check_vector(L, -1); lua_pop(L, 1); lua_getfield(L, -1, "orientation"); if (!lua_isnil(L, -1)) snap.iDir = luaL_checknumber(L, -1); lua_pop(L, 1); canvas->setSnap(snap); return 0; } static int appui_setAutoOrigin(lua_State *L) { CanvasBase *canvas = check_canvas(L, 1); Vector *v = check_vector(L, 2); canvas->setAutoOrigin(*v); return 0; } static int appui_update(lua_State *L) { CanvasBase *canvas = check_canvas(L, 1); bool all = true; if (lua_gettop(L) == 2) all = lua_toboolean(L, 2); if (all) canvas->update(); else canvas->updateTool(); return 0; } static int appui_finishTool(lua_State *L) { CanvasBase *canvas = check_canvas(L, 1); canvas->finishTool(); return 0; } static int appui_canvasSize(lua_State *L) { CanvasBase *canvas = (CanvasBase *) check_canvas(L, 1); push_vector(L, Vector(canvas->canvasWidth(), canvas->canvasHeight())); return 1; } static void check_rgb(lua_State *L, int i, int &r, int &g, int &b) { r = int(1000 * luaL_checknumber(L, i) + 0.5); g = int(1000 * luaL_checknumber(L, i+1) + 0.5); b = int(1000 * luaL_checknumber(L, i+2) + 0.5); luaL_argcheck(L, (0 <= r && r <= 1000 && 0 <= g && g <= 1000 && 0 <= b && b <= 1000), 2, "color components must be between 0.0 and 1.0"); } static int appui_setCursor(lua_State *L) { CanvasBase *canvas = check_canvas(L, 1); if (lua_isnumber(L, 2)) { double s = lua_tonumber(L, 2); int r, g, b; check_rgb(L, 3, r, g, b); Color color(r, g, b); canvas->setCursor(CanvasBase::EDotCursor, s, &color); } else if (lua_isstring(L, 2)) { static const char * const cursor_names[] = { "standard", "hand", "cross", 0 }; CanvasBase::TCursor t = CanvasBase::TCursor(luaL_checkoption(L, 2, 0, cursor_names)); canvas->setCursor(t); } else canvas->setCursor(CanvasBase::EStandardCursor); return 0; } static int appui_setNumbering(lua_State *L) { CanvasBase *canvas = check_canvas(L, 1); bool t = lua_toboolean(L, 2); CanvasBase::Style s = canvas->canvasStyle(); s.numberPages = t; canvas->setCanvasStyle(s); return 0; } // -------------------------------------------------------------------- static int appui_pantool(lua_State *L) { CanvasBase *canvas = check_canvas(L, 1); Page *page = check_page(L, 2)->page; int view = check_viewno(L, 3, page); PanTool *tool = new PanTool(canvas, page, view); canvas->setTool(tool); return 0; } static int appui_selecttool(lua_State *L) { CanvasBase *canvas = check_canvas(L, 1); Page *page = check_page(L, 2)->page; int view = check_viewno(L, 3, page); double selectDistance = luaL_checknumber(L, 4); bool nonDestructive = lua_toboolean(L, 5); SelectTool *tool = new SelectTool(canvas, page, view, selectDistance, nonDestructive); canvas->setTool(tool); return 0; } static int appui_transformtool(lua_State *L) { static const char * const option_names[] = { "translate", "scale", "stretch", "rotate", 0 }; CanvasBase *canvas = check_canvas(L, 1); Page *page = check_page(L, 2)->page; int view = check_viewno(L, 3, page); int type = luaL_checkoption(L, 4, 0, option_names); bool withShift = lua_toboolean(L, 5); lua_pushvalue(L, 6); int method = luaL_ref(L, LUA_REGISTRYINDEX); IpeTransformTool *tool = new IpeTransformTool(canvas, page, view, TransformTool::TType(type), withShift, L, method); if (tool->isValid()) { canvas->setTool(tool); lua_pushboolean(L, true); return 1; } else { delete tool; return 0; } } static int luatool_setcolor(lua_State *L) { LuaTool *tool = (LuaTool *) lua_touserdata(L, lua_upvalueindex(1)); int r, g, b; check_rgb(L, 1, r, g, b); tool->setColor(Color(r, g, b)); return 0; } static int shapetool_setshape(lua_State *L) { ShapeTool *tool = (ShapeTool *) lua_touserdata(L, lua_upvalueindex(1)); Shape shape = check_shape(L, 1); int which = 0; if (!lua_isnoneornil(L, 2)) which = luaL_checkint(L, 2); double pen = 1.0; if (lua_isnumber(L, 3)) pen = luaL_checknumber(L, 3); tool->setShape(shape, which, pen); return 0; } static int shapetool_setmarks(lua_State *L) { ShapeTool *tool = (ShapeTool *) lua_touserdata(L, lua_upvalueindex(1)); luaL_argcheck(L, lua_istable(L, 1), 1, "argument is not a table"); int no = lua_rawlen(L, 1); tool->clearMarks(); for (int i = 1; i + 1 <= no; i += 2) { lua_rawgeti(L, 1, i); luaL_argcheck(L, is_type(L, -1, "Ipe.vector"), 1, "element is not a vector"); Vector *v = check_vector(L, -1); lua_rawgeti(L, 1, i+1); luaL_argcheck(L, lua_isnumber(L, -1), 1, "element is not a number"); int t = lua_tointeger(L, -1); luaL_argcheck(L, ShapeTool::EVertex <= t && t < ShapeTool::ENumMarkTypes, 1, "number is not a mark type"); lua_pop(L, 2); // v, t tool->addMark(*v, ShapeTool::TMarkType(t)); } return 0; } static int pastetool_setmatrix(lua_State *L) { PasteTool *tool = (PasteTool *) lua_touserdata(L, lua_upvalueindex(1)); Matrix *m = check_matrix(L, 1); tool->setMatrix(*m); return 0; } static int appui_shapetool(lua_State *L) { CanvasBase *canvas = check_canvas(L, 1); lua_pushvalue(L, 2); int luatool = luaL_ref(L, LUA_REGISTRYINDEX); ShapeTool *tool = new ShapeTool(canvas, L, luatool); // add methods to Lua tool lua_rawgeti(L, LUA_REGISTRYINDEX, luatool); lua_pushlightuserdata(L, tool); lua_pushcclosure(L, luatool_setcolor, 1); lua_setfield(L, -2, "setColor"); lua_pushlightuserdata(L, tool); lua_pushcclosure(L, shapetool_setshape, 1); lua_setfield(L, -2, "setShape"); lua_pushlightuserdata(L, tool); lua_pushcclosure(L, shapetool_setmarks, 1); lua_setfield(L, -2, "setMarks"); canvas->setTool(tool); return 0; } static int appui_pastetool(lua_State *L) { CanvasBase *canvas = check_canvas(L, 1); Object *obj = check_object(L, 2)->obj; lua_pushvalue(L, 3); int luatool = luaL_ref(L, LUA_REGISTRYINDEX); PasteTool *tool = new PasteTool(canvas, L, luatool, obj->clone()); // add methods to Lua tool lua_rawgeti(L, LUA_REGISTRYINDEX, luatool); lua_pushlightuserdata(L, tool); lua_pushcclosure(L, luatool_setcolor, 1); lua_setfield(L, -2, "setColor"); lua_pushlightuserdata(L, tool); lua_pushcclosure(L, pastetool_setmatrix, 1); lua_setfield(L, -2, "setMatrix"); canvas->setTool(tool); return 0; } // -------------------------------------------------------------------- static int appui_win(lua_State *L) { AppUiBase **ui = check_appui(L, 1); push_winid(L, (*ui)->windowId()); return 1; } static int appui_close(lua_State *L) { AppUiBase **ui = check_appui(L, 1); (*ui)->closeWindow(); return 0; } static int appui_actionId(lua_State *L) { AppUiBase **ui = check_appui(L, 1); const char *action = luaL_checkstring(L, 2); lua_pushinteger(L, (*ui)->actionId(action)); return 1; } static int appui_actionState(lua_State *L) { AppUiBase **ui = check_appui(L, 1); const char *name = luaL_checkstring(L, 2); lua_pushboolean(L, (*ui)->actionState(name)); return 1; } static int appui_setActionState(lua_State *L) { AppUiBase **ui = check_appui(L, 1); const char *name = luaL_checkstring(L, 2); bool val = lua_toboolean(L, 3); (*ui)->setActionState(name, val); return 0; } static int appui_setupSymbolicNames(lua_State *L) { AppUiBase **ui = check_appui(L, 1); Cascade *sheets = check_cascade(L, 2)->cascade; (*ui)->setupSymbolicNames(sheets); return 0; } static int appui_setAttributes(lua_State *L) { AppUiBase **ui = check_appui(L, 1); Cascade *sheets = check_cascade(L, 2)->cascade; AllAttributes all; check_allattributes(L, 3, all); (*ui)->setAttributes(all, sheets); return 0; } static int appui_setGridAngleSize(lua_State *L) { AppUiBase **ui = check_appui(L, 1); Attribute gs = check_number_attribute(L, 2); Attribute as = check_number_attribute(L, 3); (*ui)->setGridAngleSize(gs, as); return 0; } static int appui_setLayers(lua_State *L) { AppUiBase **ui = check_appui(L, 1); Page *page = check_page(L, 2)->page; int view = check_viewno(L, 3, page); (*ui)->setLayers(page, view); return 0; } static int appui_setNumbers(lua_State *L) { AppUiBase **ui = check_appui(L, 1); String vno; String pno; if (!lua_isnil(L, 2)) vno = luaL_checkstring(L, 2); bool vm = lua_toboolean(L, 3); if (!lua_isnil(L, 4)) pno = luaL_checkstring(L, 4); bool pm = lua_toboolean(L, 5); (*ui)->setNumbers(vno, vm, pno, pm); return 0; } static int appui_setBookmarks(lua_State *L) { AppUiBase **ui = check_appui(L, 1); luaL_argcheck(L, lua_istable(L, 2), 2, "argument is not a table"); int no = lua_rawlen(L, 2); std::vector bm; for (int i = 1; i <= no; ++i) { lua_rawgeti(L, 2, i); luaL_argcheck(L, lua_isstring(L, -1), 2, "item is not a string"); bm.push_back(String(lua_tostring(L, -1))); lua_pop(L, 1); } (*ui)->setBookmarks(no, &bm[0]); return 0; } static int appui_setWindowTitle(lua_State *L) { AppUiBase **ui = check_appui(L, 1); bool mod = lua_toboolean(L, 2); const char *s = luaL_checkstring(L, 3); (*ui)->setWindowCaption(mod, s); return 0; } static int appui_setNotes(lua_State *L) { AppUiBase **ui = check_appui(L, 1); const char *s = luaL_checkstring(L, 2); (*ui)->setNotes(s); return 0; } static int appui_showTool(lua_State *L) { static const char * const option_names[] = { "properties", "bookmarks", "notes", "layers", 0 }; AppUiBase **ui = check_appui(L, 1); int m = luaL_checkoption(L, 2, 0, option_names); bool s = lua_toboolean(L, 3); (*ui)->setToolVisible(m, s); return 0; } static int appui_explain(lua_State *L) { AppUiBase **ui = check_appui(L, 1); const char *s = luaL_checkstring(L, 2); int t = 4000; if (lua_isnumber(L, 3)) t = lua_tointeger(L, 3); (*ui)->explain(s, t); return 0; } // -------------------------------------------------------------------- #if IPEUI_QT static void get_page_sorter_size(lua_State *L, int &width, int &height, int &thumbWidth) { thumbWidth = 300; width = 600; height = 480; lua_getglobal(L, "prefs"); lua_getfield(L, -1, "page_sorter_size"); if (lua_istable(L, -1)) { lua_rawgeti(L, -1, 1); if (lua_isnumber(L, -1)) width = lua_tointeger(L, -1); lua_rawgeti(L, -2, 2); if (lua_isnumber(L, -1)) height = lua_tointeger(L, -1); lua_pop(L, 2); } lua_pop(L, 1); // page_sorter_size lua_getfield(L, -1, "thumbnail_width"); if (lua_isnumber(L, -1)) thumbWidth = lua_tointeger(L, -1); lua_pop(L, 1); // thumbnail_width, prefs } #endif static int appui_selectPage(lua_State *L) { #if IPEUI_QT AppUiBase **ui = check_appui(L, 1); (void) ui; // not actually used now Document **doc = check_document(L, 2); int page = -1; if (lua_isnumber(L, 3)) { page = lua_tointeger(L, 3); luaL_argcheck(L, 1 <= page && page <= (*doc)->countPages(), 3, "invalid page number"); } int startIndex = 1; if (lua_isnumber(L, 4)) { startIndex = lua_tointeger(L, 4); int maxIndex = (page < 0) ? (*doc)->countPages() : (*doc)->page(page-1)->countViews(); luaL_argcheck(L, 1 <= startIndex && startIndex <= maxIndex, 4, "invalid start index"); } int width, height, thumbWidth; get_page_sorter_size(L, width, height, thumbWidth); int sel = PageSelector::selectPageOrView(*doc, page - 1, startIndex - 1, thumbWidth, width, height); if (sel >= 0) { lua_pushinteger(L, sel + 1); return 1; } else #endif return 0; } static int appui_pageSorter(lua_State *L) { #ifdef IPEUI_QT AppUiBase **ui = check_appui(L, 1); (void) ui; // not actually used now Document **doc = check_document(L, 2); int width, height, thumbWidth; get_page_sorter_size(L, width, height, thumbWidth); QDialog *d = new QDialog(); d->setWindowTitle("Ipe Page Sorter"); QLayout *lo = new QVBoxLayout; PageSorter *p = new PageSorter(*doc, thumbWidth); QDialogButtonBox *buttonBox = new QDialogButtonBox(QDialogButtonBox::Ok|QDialogButtonBox::Cancel); lo->addWidget(p); lo->addWidget(buttonBox); d->setLayout(lo); d->connect(buttonBox, SIGNAL(accepted()), SLOT(accept())); d->connect(buttonBox, SIGNAL(rejected()), SLOT(reject())); d->resize(width, height); if (d->exec() == QDialog::Rejected) { delete d; return 0; } lua_createtable(L, p->count(), 0); for (int i = 1; i <= p->count(); ++i) { lua_pushinteger(L, p->pageAt(i-1) + 1); lua_rawseti(L, -2, i); } delete d; return 1; #else return 0; #endif } // -------------------------------------------------------------------- static const struct luaL_Reg appui_methods[] = { { "__tostring", appui_tostring }, { "__gc", appui_destructor }, // -------------------------------------------------------------------- { "setPage", appui_setPage}, { "pan", appui_pan}, { "setPan", appui_setPan}, { "zoom", appui_zoom}, { "setZoom", appui_setZoom}, { "setFontPool", appui_setFontPool}, { "pos", appui_pos}, { "globalPos", appui_globalPos}, { "unsnappedPos", appui_unsnappedPos}, { "simpleSnapPos", appui_simpleSnapPos }, { "setFifiVisible", appui_setFifiVisible}, { "setSelectionVisible", appui_setSelectionVisible}, { "setSnap", appui_setSnap}, { "setAutoOrigin", appui_setAutoOrigin }, { "update", appui_update}, { "finishTool", appui_finishTool}, { "canvasSize", appui_canvasSize }, { "setCursor", appui_setCursor }, { "setNumbering", appui_setNumbering }, // -------------------------------------------------------------------- { "panTool", appui_pantool }, { "selectTool", appui_selecttool }, { "transformTool", appui_transformtool }, { "shapeTool", appui_shapetool }, { "pasteTool", appui_pastetool }, // -------------------------------------------------------------------- { "win", appui_win}, { "close", appui_close}, { "setActionState", appui_setActionState }, { "actionState", appui_actionState }, { "actionId", appui_actionId }, { "explain", appui_explain }, { "setWindowTitle", appui_setWindowTitle }, { "setupSymbolicNames", appui_setupSymbolicNames }, { "setAttributes", appui_setAttributes }, { "setGridAngleSize", appui_setGridAngleSize }, { "setLayers", appui_setLayers }, { "setNumbers", appui_setNumbers }, { "setBookmarks", appui_setBookmarks }, { "setNotes", appui_setNotes }, { "showTool", appui_showTool }, { "selectPage", appui_selectPage }, { "pageSorter", appui_pageSorter }, { 0, 0}, }; // -------------------------------------------------------------------- static int appui_constructor(lua_State *L) { luaL_checktype(L, 1, LUA_TTABLE); // this is the model AppUiBase **ui = (AppUiBase **) lua_newuserdata(L, sizeof(AppUiBase *)); *ui = 0; luaL_getmetatable(L, "Ipe.appui"); lua_setmetatable(L, -2); lua_pushvalue(L, 1); int model = luaL_ref(L, LUA_REGISTRYINDEX); *ui = createAppUi(L, model); CanvasBase::Style style; style.pretty = false; style.paperColor = Color(1000,1000,1000); style.classicGrid = false; style.thinLine = 0.2; style.thickLine = 0.9; style.thinStep = 1; style.thickStep = 4; style.paperClip = false; style.numberPages = false; lua_getglobal(L, "prefs"); lua_getfield(L, -1, "canvas_style"); if (!lua_isnil(L, -1)) { lua_getfield(L, -1, "paper_color"); if (!lua_isnil(L, -1)) style.paperColor = check_color(L, lua_gettop(L)); lua_pop(L, 1); // paper_color lua_getfield(L, -1, "classic_grid"); style.classicGrid = lua_toboolean(L, -1); lua_pop(L, 1); // classic_grid lua_getfield(L, -1, "thin_grid_line"); if (lua_isnumber(L, -1)) style.thinLine = lua_tonumber(L, -1); lua_pop(L, 1); // thin_grid_line lua_getfield(L, -1, "thick_grid_line"); if (lua_isnumber(L, -1)) style.thickLine = lua_tonumber(L, -1); lua_pop(L, 1); // thick_grid_line lua_getfield(L, -1, "thin_step"); if (lua_isnumber(L, -1)) style.thinStep = lua_tointeger(L, -1); lua_pop(L, 1); // thin_step lua_getfield(L, -1, "thick_step"); if (lua_isnumber(L, -1)) style.thickStep = lua_tointeger(L, -1); lua_pop(L, 1); // thick_step } lua_pop(L, 1); // canvas_style int width = -1, height = -1; lua_getfield(L, -1, "window_size"); if (lua_istable(L, -1)) { lua_rawgeti(L, -1, 1); if (lua_isnumber(L, -1)) width = lua_tointeger(L, -1); lua_rawgeti(L, -2, 2); if (lua_isnumber(L, -1)) height = lua_tointeger(L, -1); lua_pop(L, 2); } lua_pop(L, 1); // window_size lua_pop(L, 1); // prefs (*ui)->canvas()->setCanvasStyle(style); (*ui)->showWindow(width, height); return 1; } // -------------------------------------------------------------------- int luaopen_appui(lua_State *L) { lua_pushcfunction(L, appui_constructor); lua_setglobal(L, "AppUi"); make_metatable(L, "Ipe.appui", appui_methods); return 0; } // -------------------------------------------------------------------- ipe-7.1.4/src/ipe/appui_win.cpp0000644000175000017500000010163312120621776016225 0ustar otfriedotfried// -------------------------------------------------------------------- // AppUi for Win32 // -------------------------------------------------------------------- /* This file is part of the extensible drawing editor Ipe. Copyright (C) 1993-2013 Otfried Cheong Ipe is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. As a special exception, you have permission to link Ipe with the CGAL library and distribute executables, as long as you follow the requirements of the Gnu General Public License in regard to all of the software in the executable aside from CGAL. Ipe 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 General Public License for more details. You should have received a copy of the GNU General Public License along with Ipe; if not, you can find it at "http://www.gnu.org/copyleft/gpl.html", or write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ #include "appui_win.h" #include "ipecanvas_win.h" #include "controls_win.h" #include "ipelua.h" // for version info only #include "ipefonts.h" #include #include #include #include #include #define IDI_MYICON 1 #define ID_STATUS_TIMER 1 #define IDC_STATUSBAR 7000 #define IDC_BOOKMARK 7100 #define IDC_NOTES 7200 #define IDBASE 8000 #define TEXT_STYLE_BASE 8300 #define SELECT_LAYER_BASE 8400 #define ID_SELECTOR_BASE 8500 #define ID_ABSOLUTE_BASE 8600 #define ID_PATHVIEW 8700 using namespace ipe; using namespace ipelua; // -------------------------------------------------------------------- const int TBICONSIZE = 24; static HINSTANCE win_hInstance = 0; static int win_nCmdShow = 0; const char AppUi::className[] = "ipeWindowClass"; // -------------------------------------------------------------------- static HBITMAP loadIcon(String action, int size) { String dir = ipeIconDirectory(); String fname = dir + action + ".png"; if (!Platform::fileExists(fname)) return NULL; cairo_surface_t *sf = cairo_image_surface_create_from_png(fname.z()); assert(cairo_image_surface_get_format(sf) == CAIRO_FORMAT_ARGB32); unsigned char *p = cairo_image_surface_get_data(sf); int wd = cairo_image_surface_get_width(sf); int ht = cairo_image_surface_get_height(sf); int stride = cairo_image_surface_get_stride(sf); HDC hdc = GetDC(NULL); BITMAPINFO bmi; ZeroMemory(&bmi, sizeof(bmi)); bmi.bmiHeader.biSize = sizeof(BITMAPINFOHEADER); bmi.bmiHeader.biWidth = size; bmi.bmiHeader.biHeight = size; bmi.bmiHeader.biPlanes = 1; bmi.bmiHeader.biBitCount = 32; bmi.bmiHeader.biCompression = BI_RGB; void *pbits = 0; HBITMAP bm = CreateDIBSection(hdc, &bmi, DIB_RGB_COLORS, &pbits, NULL, 0); // make it transparent unsigned char *q = (unsigned char *) pbits; for (unsigned char *r = q; r < q + 4 * size * size;) *r++ = 0x00; int x0 = wd < size ? (size - wd)/2 : 0; int y0 = ht < size ? (size - ht)/2 : 0; int xs = wd > size ? size : wd; int ys = ht > size ? size : ht; for (int y = 0; y < ys; ++y) { unsigned char *src = p + (ht - 1 - y) * stride; unsigned char *dst = q + (y0 + y) * (4 * size) + 4 * x0; int n = 4 * xs; while (n--) *dst++ = *src++; } cairo_surface_destroy(sf); ReleaseDC(NULL, hdc); return bm; } static int loadIcon(String action, HIMAGELIST il) { HBITMAP bm = loadIcon(action, TBICONSIZE); if (bm == NULL) return -1; int r = ImageList_Add(il, bm, NULL); DeleteObject(bm); return r; } static HBITMAP loadButtonIcon(String action) { String dir = ipeIconDirectory(); String fname = dir + action + ".png"; if (!Platform::fileExists(fname)) return NULL; cairo_surface_t *sf = cairo_image_surface_create_from_png(fname.z()); assert(cairo_image_surface_get_format(sf) == CAIRO_FORMAT_ARGB32); unsigned char *p = cairo_image_surface_get_data(sf); int wd = cairo_image_surface_get_width(sf); int ht = cairo_image_surface_get_height(sf); int stride = cairo_image_surface_get_stride(sf); HDC hdc = GetDC(NULL); BITMAPINFO bmi; ZeroMemory(&bmi, sizeof(bmi)); bmi.bmiHeader.biSize = sizeof(BITMAPINFOHEADER); bmi.bmiHeader.biWidth = wd; bmi.bmiHeader.biHeight = ht; bmi.bmiHeader.biPlanes = 1; bmi.bmiHeader.biBitCount = 24; bmi.bmiHeader.biCompression = BI_RGB; void *pbits = 0; HBITMAP bm = CreateDIBSection(hdc, &bmi, DIB_RGB_COLORS, &pbits, NULL, 0); DWORD rgb = GetSysColor(COLOR_BTNFACE); int r0 = GetRValue(rgb); int g0 = GetGValue(rgb); int b0 = GetBValue(rgb); unsigned char *q = (unsigned char *) pbits; int dstride = (3 * wd + 3) & (~3); for (int x = 0; x < wd; ++x) { for (int y = 0; y < ht; ++y) { unsigned char *src = p + (ht - 1 - y) * stride + 4 * x; unsigned char *dst = q + y * dstride + 3 * x; int r1 = *src++; int g1 = *src++; int b1 = *src++; int trans = *src++; *dst++ = r1 + int((0xff - trans) * r0 / 0xff); *dst++ = g1 + int((0xff - trans) * g0 / 0xff); *dst++ = b1 + int((0xff - trans) * b0 / 0xff); } } cairo_surface_destroy(sf); ReleaseDC(NULL, hdc); return bm; } static HBITMAP colorIcon(Color color) { int r = int(color.iRed.internal() * 255 / 1000); int g = int(color.iGreen.internal() * 255 / 1000); int b = int(color.iBlue.internal() * 255 / 1000); COLORREF rgb = RGB(r, g, b); int cx = 22; int cy = 22; HDC hdc = GetDC(NULL); HDC memDC = CreateCompatibleDC(hdc); HBITMAP bm = CreateCompatibleBitmap(hdc, cx, cy); SelectObject(memDC, bm); for (int y = 0; y < cy; ++y) { for (int x = 0; x < cx; ++x) { SetPixel(memDC, x, y, rgb); } } DeleteDC(memDC); ReleaseDC(NULL, hdc); return bm; } // -------------------------------------------------------------------- void AppUi::addRootMenu(int id, const char *name) { hRootMenu[id] = CreatePopupMenu(); AppendMenu(hMenuBar, MF_STRING | MF_POPUP, UINT(hRootMenu[id]), name); } void AppUi::createAction(String name, String tooltip, bool canWhileDrawing) { SAction s; s.name = String(name); s.icon = loadIcon(name, hIcons); s.tooltip = tooltip; s.alwaysOn = canWhileDrawing; iActions.push_back(s); } void AppUi::addItem(HMENU menu, const char *title, const char *name) { if (title == 0) { AppendMenu(menu, MF_SEPARATOR, 0, 0); } else { bool canUseWhileDrawing = false; if (name[0] == '@') { canUseWhileDrawing = true; name = name + 1; } if (name[0] == '*') name += 1; // in Win32 all menu items are checkable anyway // check for shortcut lua_getglobal(L, "shortcuts"); lua_getfield(L, -1, name); String sc; if (lua_isstring(L, -1)) { sc = lua_tostring(L, -1); } else if (lua_istable(L, -1) && lua_objlen(L, -1) > 0) { lua_rawgeti(L, -1, 1); if (lua_isstring(L, -1)) sc = lua_tostring(L, -1); lua_pop(L, 1); // pop string } lua_pop(L, 2); // shortcuts, shortcuts[name] String tooltip = title; if (!sc.isEmpty()) tooltip = tooltip + " [" + sc + "]"; createAction(name, tooltip, canUseWhileDrawing); if (sc.isEmpty()) AppendMenu(menu, MF_STRING, iActions.size() - 1 + IDBASE, title); else { String t = title; t += "\t"; t += sc; AppendMenu(menu, MF_STRING, iActions.size() - 1 + IDBASE, t.z()); } } } void AppUi::addItem(int id, const char *title, const char *name) { addItem(hRootMenu[id], title, name); } static HMENU submenu = 0; void AppUi::startSubMenu(int id, const char *name) { submenu = CreatePopupMenu(); AppendMenu(hRootMenu[id], MF_STRING | MF_POPUP, UINT(submenu), name); } void AppUi::addSubItem(const char *title, const char *name) { addItem(submenu, title, name); } MENUHANDLE AppUi::endSubMenu() { return submenu; } void AppUi::addTButton(HWND tb, const char *name, int flags) { TBBUTTON tbb; ZeroMemory(&tbb, sizeof(tbb)); if (name == 0) { tbb.iBitmap = 1; tbb.fsStyle = TBSTYLE_SEP; } else { int i = findAction(name); tbb.iBitmap = iconId(name); tbb.fsState = TBSTATE_ENABLED; tbb.fsStyle = TBSTYLE_BUTTON | flags; tbb.idCommand = i + IDBASE; tbb.iString = INT_PTR(iActions[i].tooltip.z()); } SendMessage(tb, TB_ADDBUTTONS, 1, (LPARAM) &tbb); } void AppUi::setTooltip(HWND h, String tip, bool isComboBoxEx) { if (isComboBoxEx) h = (HWND) SendMessage(h, CBEM_GETCOMBOCONTROL, 0, 0); TOOLINFO toolInfo = { 0 }; toolInfo.cbSize = sizeof(toolInfo); toolInfo.hwnd = hwnd; toolInfo.uFlags = TTF_IDISHWND | TTF_SUBCLASS; toolInfo.uId = (UINT_PTR) h; toolInfo.lpszText = (char *) tip.z(); SendMessage(hTip, TTM_ADDTOOL, 0, (LPARAM) &toolInfo); } HWND AppUi::createButton(HINSTANCE hInst, int id, int flags) { return CreateWindowEx(0, "button", NULL, WS_CHILD | WS_VISIBLE | flags, 0, 0, 0, 0, hwnd, (HMENU) id, hInst, NULL); } // -------------------------------------------------------------------- AppUi::AppUi(lua_State *L0, int model) : AppUiBase(L0, model) { // windows procedure may receive WM_SIZE message before canvas is created iCanvas = 0; HWND hwnd = CreateWindowEx(WS_EX_CLIENTEDGE, className, "Ipe", WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, NULL, NULL, win_hInstance, this); if (hwnd == NULL) { MessageBox(NULL, "AppUi window creation failed!", "Error!", MB_ICONEXCLAMATION | MB_OK); exit(9); } assert(GetWindowLongPtr(hwnd, GWLP_USERDATA)); } // called during Window creation void AppUi::initUi() { hIcons = ImageList_Create(TBICONSIZE, TBICONSIZE, ILC_COLOR32, 4, 4); HINSTANCE hInst = (HINSTANCE) GetWindowLong(hwnd, GWL_HINSTANCE); hMenuBar = CreateMenu(); buildMenus(); SetMenu(hwnd, hMenuBar); hStatusBar = CreateWindowEx(0, STATUSCLASSNAME, NULL, WS_CHILD | WS_VISIBLE | SBARS_SIZEGRIP, 0, 0, 0, 0, hwnd, (HMENU) IDC_STATUSBAR, hInst, NULL); hTip = CreateWindowEx(0, TOOLTIPS_CLASS, NULL, WS_POPUP | TTS_NOPREFIX | TTS_ALWAYSTIP, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, hwnd, NULL, hInst, NULL); SetWindowPos(hTip, HWND_TOPMOST, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE | SWP_NOACTIVATE); // if used in Rebar, need CCS_NOPARENTALIGN | CCS_NORESIZE, hToolBar = CreateWindowEx(0, TOOLBARCLASSNAME, NULL, WS_CHILD | WS_VISIBLE | TBSTYLE_WRAPABLE | TBSTYLE_TOOLTIPS, 0, 0, 0, 0, hwnd, NULL, hInst, NULL); SendMessage(hToolBar, TB_BUTTONSTRUCTSIZE, (WPARAM) sizeof(TBBUTTON), 0); SendMessage(hToolBar, TB_SETIMAGELIST, 0, (LPARAM) hIcons); // SendMessage(hToolBar, TB_SETBUTTONSIZE, 0, MAKELPARAM(48, 48)); SendMessage(hToolBar, TB_SETMAXTEXTROWS, 0, (LPARAM) 0); HWND hSnapTools = hToolBar; addTButton(hSnapTools, "snapvtx", BTNS_CHECK); addTButton(hSnapTools, "snapbd", BTNS_CHECK); addTButton(hSnapTools, "snapint", BTNS_CHECK); addTButton(hSnapTools, "snapgrid", BTNS_CHECK); addTButton(hSnapTools, "snapangle", BTNS_CHECK); addTButton(hSnapTools, "snapauto", BTNS_CHECK); addTButton(hToolBar); // separator HWND hEditTools = hToolBar; addTButton(hEditTools, "copy"); addTButton(hEditTools, "cut"); addTButton(hEditTools, "paste"); addTButton(hEditTools, "delete"); addTButton(hEditTools, "undo"); addTButton(hEditTools, "redo"); addTButton(hEditTools, "zoom_in"); addTButton(hEditTools, "zoom_out"); addTButton(hEditTools, "fit_objects"); addTButton(hEditTools, "fit_page"); addTButton(hEditTools, "fit_width"); addTButton(hEditTools, "keyboard"); createAction("shift_key", String()); addTButton(hEditTools, "shift_key", BTNS_CHECK); addTButton(hToolBar); // separator HWND hObjectTools = hToolBar; addTButton(hObjectTools, "mode_select", BTNS_CHECKGROUP); addTButton(hObjectTools, "mode_translate", BTNS_CHECKGROUP); addTButton(hObjectTools, "mode_rotate", BTNS_CHECKGROUP); addTButton(hObjectTools, "mode_stretch", BTNS_CHECKGROUP); addTButton(hObjectTools, "mode_pan", BTNS_CHECKGROUP); addTButton(hObjectTools, "mode_label", BTNS_CHECKGROUP); addTButton(hObjectTools, "mode_math", BTNS_CHECKGROUP); addTButton(hObjectTools, "mode_paragraph", BTNS_CHECKGROUP); addTButton(hObjectTools, "mode_marks", BTNS_CHECKGROUP); addTButton(hObjectTools, "mode_rectangles", BTNS_CHECKGROUP); addTButton(hObjectTools, "mode_lines", BTNS_CHECKGROUP); addTButton(hObjectTools, "mode_polygons", BTNS_CHECKGROUP); addTButton(hObjectTools, "mode_splines", BTNS_CHECKGROUP); addTButton(hObjectTools, "mode_splinegons", BTNS_CHECKGROUP); addTButton(hObjectTools, "mode_arc1", BTNS_CHECKGROUP); addTButton(hObjectTools, "mode_arc2", BTNS_CHECKGROUP); addTButton(hObjectTools, "mode_arc3", BTNS_CHECKGROUP); addTButton(hObjectTools, "mode_circle1", BTNS_CHECKGROUP); addTButton(hObjectTools, "mode_circle2", BTNS_CHECKGROUP); addTButton(hObjectTools, "mode_circle3", BTNS_CHECKGROUP); addTButton(hObjectTools, "mode_ink", BTNS_CHECKGROUP); SendMessage(hToolBar, TB_AUTOSIZE, 0, 0); #if 0 // maybe later I'll put the toolbars in a Rebar // Create the rebar. hRebar = CreateWindowEx(WS_EX_TOOLWINDOW, REBARCLASSNAME, NULL, WS_CHILD | WS_VISIBLE | WS_CLIPSIBLINGS | WS_CLIPCHILDREN | RBS_VARHEIGHT | CCS_NODIVIDER | RBS_BANDBORDERS, 0, 0, 0, 0, hwnd, NULL, hInst, NULL); REBARINFO ri = {0}; ri.cbSize = sizeof(REBARINFO); SendMessage(hRebar, RB_SETBARINFO, 0, (LPARAM) &ri); // Initialize band info for all bands REBARBANDINFO rbBand = { sizeof(REBARBANDINFO) }; rbBand.fMask = RBBIM_STYLE // fStyle is valid. | RBBIM_TEXT // lpText is valid. | RBBIM_CHILD // hwndChild is valid. | RBBIM_CHILDSIZE // child size members are valid. | RBBIM_SIZE; // cx is valid rbBand.fStyle = RBBS_CHILDEDGE | RBBS_GRIPPERALWAYS; // Get the height of the toolbars. DWORD dwBtnSize = (DWORD) SendMessage(hEditTools, TB_GETBUTTONSIZE, 0, 0); rbBand.lpText = (char *) "Edit"; rbBand.hwndChild = hEditTools; rbBand.cyChild = LOWORD(dwBtnSize); rbBand.cxMinChild = 14 * HIWORD(dwBtnSize); rbBand.cyMinChild = 40; // The default width is the width of the buttons. rbBand.cx = 0; // Add the band. SendMessage(hRebar, RB_INSERTBAND, (WPARAM)-1, (LPARAM) &rbBand); rbBand.lpText = (char *) "Snap"; rbBand.hwndChild = hSnapTools; rbBand.cxMinChild = 6 * HIWORD(dwBtnSize); SendMessage(hRebar, RB_INSERTBAND, (WPARAM)-1, (LPARAM) &rbBand); #endif hProperties = CreateWindowEx(0, "button", "Properties", WS_CHILD | WS_VISIBLE | BS_GROUPBOX, 0, 100, 200, 280, hwnd, NULL, hInst, NULL); for (int i = 0; i <= EUiSymbolSize; ++i) { if (i != EUiMarkShape) hButton[i] = createButton(hInst, ID_ABSOLUTE_BASE + i); } for (int i = 0; i < EUiView; ++i) hSelector[i] = CreateWindowEx(0, WC_COMBOBOXEX, NULL, WS_CHILD | WS_VISIBLE | CBS_DROPDOWNLIST, 0, 0, 0, 0, hwnd, (HMENU) (ID_SELECTOR_BASE + i), hInst, NULL); SendMessage(hButton[EUiPen], BM_SETIMAGE, IMAGE_BITMAP, (LPARAM) loadButtonIcon("pen")); SendMessage(hButton[EUiTextSize], BM_SETIMAGE, IMAGE_BITMAP, (LPARAM) loadButtonIcon("mode_label")); SendMessage(hButton[EUiSymbolSize], BM_SETIMAGE, IMAGE_BITMAP, (LPARAM) loadButtonIcon("mode_marks")); SendMessage(hButton[EUiStroke], BM_SETIMAGE, IMAGE_BITMAP, (LPARAM) colorIcon(Color(1000, 0, 0))); SendMessage(hButton[EUiFill], BM_SETIMAGE, IMAGE_BITMAP, (LPARAM) colorIcon(Color(1000, 1000, 0))); hButton[EUiMarkShape] = CreateWindowEx(0, "static", NULL, WS_CHILD | WS_VISIBLE | SS_BITMAP | SS_CENTERIMAGE, 0, 0, 0, 0, hwnd, NULL, hInst, NULL); SendMessage(hButton[EUiMarkShape], STM_SETIMAGE, IMAGE_BITMAP, (LPARAM) loadButtonIcon("mode_marks")); hViewNumber = createButton(hInst, ID_ABSOLUTE_BASE + EUiView, BS_TEXT|BS_PUSHBUTTON); hPageNumber = createButton(hInst, ID_ABSOLUTE_BASE + EUiPage, BS_TEXT|BS_PUSHBUTTON); hViewMarked = createButton(hInst, ID_ABSOLUTE_BASE + EUiViewMarked, BS_AUTOCHECKBOX); hPageMarked = createButton(hInst, ID_ABSOLUTE_BASE + EUiPageMarked, BS_AUTOCHECKBOX); hNotes = CreateWindowEx(0, "edit", NULL, WS_CHILD | WS_VSCROLL | WS_BORDER | ES_READONLY | ES_LEFT | ES_MULTILINE | ES_AUTOVSCROLL, 0, 0, 0, 0, hwnd, (HMENU) IDC_NOTES, hInst, NULL); hBookmarks = CreateWindowEx(0, "listbox", NULL, WS_CHILD | WS_VSCROLL | WS_BORDER | LBS_HASSTRINGS | LBS_NOTIFY | LBS_NOSEL, 0, 0, 0, 0, hwnd, (HMENU) IDC_BOOKMARK, hInst, NULL); iPathView = new PathView(hwnd, ID_PATHVIEW); Canvas *canvas = new Canvas(hwnd); hwndCanvas = canvas->windowId(); iCanvas = canvas; iCanvas->setObserver(this); // Tooltips setTooltip(hButton[EUiStroke], "Absolute stroke color"); setTooltip(hButton[EUiFill], "Absolute fill color"); setTooltip(hButton[EUiPen], "Absolute pen width"); setTooltip(hButton[EUiTextSize], "Absolute text size"); setTooltip(hButton[EUiSymbolSize], "Absolute symbol size"); setTooltip(hSelector[EUiStroke], "Symbolic stroke color", true); setTooltip(hSelector[EUiFill], "Symbolic fill color", true); setTooltip(hSelector[EUiPen], "Symbolic pen width", true); setTooltip(hSelector[EUiTextSize], "Symbolic text size", true); setTooltip(hSelector[EUiMarkShape], "Mark shape", true); setTooltip(hSelector[EUiSymbolSize], "Symbolic symbol size", true); setTooltip(hSelector[EUiGridSize], "Grid size", true); setTooltip(hSelector[EUiAngleSize], "Angle for angular snap", true); setTooltip(hViewNumber, "Current view number"); setTooltip(hPageNumber, "Current page number"); setTooltip(hNotes, "Notes for this page"); setTooltip(hBookmarks, "Bookmarks of this document"); // TODO setTooltip(hLayerList, "Layers of this page"); setCheckMark("coordinates|", "points"); setCheckMark("mode_", "select"); } AppUi::~AppUi() { // canvas is deleted by Windows ?? ImageList_Destroy(hIcons); KillTimer(hwnd, ID_STATUS_TIMER); } void AppUi::layoutChildren() { RECT rc, rc1, rc2; GetClientRect(hwnd, &rc); SendMessage(hStatusBar, WM_SIZE, 0, 0); SendMessage(hToolBar, TB_AUTOSIZE, 0, 0); GetClientRect(hStatusBar, &rc1); GetClientRect(hToolBar, &rc2); int sbh = rc1.bottom - rc1.top; int tbh = rc2.bottom - rc2.top; int cvh = rc.bottom - sbh - tbh; RECT rect; rect.left = 0; rect.top = tbh; rect.right = 200; rect.bottom = rc.bottom; InvalidateRect(hwnd, &rect, TRUE); MoveWindow(hProperties, 10, tbh, 180, 320, TRUE); for (int i = 0; i <= EUiSymbolSize; ++i) MoveWindow(hButton[i], 20, tbh + 50 + 30 * i, 26, 26, TRUE); for (int i = 0; i < EUiView; ++i) { int x = (i == EUiGridSize) ? 10 : (i == EUiAngleSize) ? 100 : 60; int y = (i >= EUiGridSize) ? 20 : 50 + 30 * i; int w = (i >= EUiGridSize) ? 70 : 110; MoveWindow(hSelector[i], 10 + x, tbh + y, w, 26, TRUE); } MoveWindow(hViewNumber, 20, tbh + 240, 60, 26, TRUE); MoveWindow(hPageNumber, 120, tbh + 240, 60, 26, TRUE); MoveWindow(hViewMarked, 85, tbh + 245, 20, 20, TRUE); MoveWindow(hPageMarked, 100, tbh + 245, 20, 20, TRUE); MoveWindow(iPathView->windowId(), 20, tbh + 270, 160, 40, TRUE); bool visNotes = IsWindowVisible(hNotes); bool visBookmarks = IsWindowVisible(hBookmarks); int cvw = (visNotes || visBookmarks) ? rc.right - 400 : rc.right - 200; MoveWindow(hwndCanvas, 200, tbh, cvw, cvh, TRUE); int nth = (visNotes && visBookmarks) ? cvh / 2 : cvh; int nty = tbh; if (visNotes) { MoveWindow(hNotes, rc.right - 200, nty, 200, nth, TRUE); nty += nth; } if (visBookmarks) MoveWindow(hBookmarks, rc.right - 200, nty, 200, nth, TRUE); int statwidths[] = {rc.right - 200, rc.right - 80, rc.right }; SendMessage(hStatusBar, SB_SETPARTS, 3, (LPARAM) statwidths); iCanvas->update(); } // -------------------------------------------------------------------- // add item to ComboBoxEx static void addComboEx(HWND h, String s) { COMBOBOXEXITEM item; item.mask = CBEIF_TEXT; item.iItem = (INT_PTR) -1; item.pszText = (char *) s.z(); SendMessage(h, CBEM_INSERTITEM, 0, (LPARAM) &item); } void AppUi::resetCombos() { for (int i = 0; i < EUiView; ++i) SendMessage(hSelector[i], CB_RESETCONTENT, 0, 0); } void AppUi::addComboColor(int sel, String s, Color color) { // TODO QIcon icon = prefsColorIcon(color); addComboEx(hSelector[sel], s); } void AppUi::addCombo(int sel, String s) { addComboEx(hSelector[sel], s); } void AppUi::setComboCurrent(int sel, int idx) { SendMessage(hSelector[sel], CB_SETCURSEL, idx, 0); } void AppUi::setButtonColor(int sel, Color color) { SendMessage(hButton[sel], BM_SETIMAGE, IMAGE_BITMAP, (LPARAM) colorIcon(color)); } void AppUi::setPathView(const AllAttributes &all, Cascade *sheet) { iPathView->set(all, sheet); } void AppUi::setCheckMark(String name, Attribute a) { setCheckMark(name + "|", a.string()); } void AppUi::setCheckMark(String name, String value) { String sa = name; int na = sa.size(); String sb = sa + value; int first = -1; int last = -1; int check = -1; for (int i = 0; i < int(iActions.size()); ++i) { if (iActions[i].name.left(na) == sa) { if (first < 0) first = IDBASE + i; last = IDBASE + i; if (iActions[i].name == sb) check = IDBASE + i; } } ipeDebug("CheckMenuRadioItem %s %d %d %d", name.z(), first, last, check); if (check > 0) CheckMenuRadioItem(hMenuBar, first, last, check, MF_BYCOMMAND); if (name == "mode_") { for (int i = 0; i < int(iActions.size()); ++i) { if (iActions[i].name.left(na) == sa) { int id = IDBASE + i; int state = TBSTATE_ENABLED; if (id == check) state |= TBSTATE_CHECKED; SendMessage(hToolBar, TB_SETSTATE, id, (LPARAM) state); } } } } void AppUi::setLayers(const Page *page, int view) { // TODO } void AppUi::setActionsEnabled(bool mode) { int mstate = mode ? MF_ENABLED : MF_GRAYED; int tstate = mode ? TBSTATE_ENABLED : 0; for (int i = 0; i < int(iActions.size()); ++i) { int id = i + IDBASE; if (!iActions[i].alwaysOn) { EnableMenuItem(hMenuBar, id, mstate); int ostate = SendMessage(hToolBar, TB_GETSTATE, id, 0); if (ostate != -1) SendMessage(hToolBar, TB_SETSTATE, id, (LPARAM) ((ostate & TBSTATE_CHECKED)|tstate)); } } EnableWindow(hNotes, mode); EnableWindow(hBookmarks, mode); } void AppUi::setNumbers(String vno, bool vm, String pno, bool pm) { SetWindowText(hViewNumber, vno.z()); SetWindowText(hPageNumber, pno.z()); Button_SetCheck(hViewMarked, vm ? BST_CHECKED : BST_UNCHECKED); Button_SetCheck(hPageMarked, pm ? BST_CHECKED : BST_UNCHECKED); EnableWindow(hViewNumber, !vno.isEmpty()); EnableWindow(hViewMarked, !vno.isEmpty()); EnableWindow(hPageNumber, !pno.isEmpty()); EnableWindow(hPageMarked, !pno.isEmpty()); } void AppUi::setNotes(String notes) { Edit_SetText(hNotes, notes.z()); } void AppUi::closeRequested() { // calls model lua_rawgeti(L, LUA_REGISTRYINDEX, iModel); lua_getfield(L, -1, "closeEvent"); lua_pushvalue(L, -2); // model lua_remove(L, -3); lua_call(L, 1, 1); bool result = lua_toboolean(L, -1); if (result) DestroyWindow(hwnd); } void AppUi::closeWindow() { SendMessage(hwnd, WM_CLOSE, 0, 0); } // Determine if an action is checked. // Used for viewmarked, pagemarked, snapXXX, and grid_visible bool AppUi::actionState(const char *name) { ipeDebug("actionState %s", name); int idx = actionId(name); return GetMenuState(hMenuBar, idx, MF_CHECKED); } // Check/uncheck an action. // Used by Lua for snapangle and grid_visible // Also to initialize mode_select // Used from AppUi::action to toggle snapXXX, grid_visible void AppUi::setActionState(const char *name, bool value) { ipeDebug("setActionState %s %d", name, value); int idx = actionId(name); CheckMenuItem(hMenuBar, idx, value ? MF_CHECKED : MF_UNCHECKED); int state = TBSTATE_ENABLED; if (value) state |= TBSTATE_CHECKED; SendMessage(hToolBar, TB_SETSTATE, idx, (LPARAM) state); } void AppUi::setBookmarks(int no, const String *s) { SendMessage(hBookmarks, LB_RESETCONTENT, 0, 0); for (int i = 0; i < no; ++i) SendMessage(hBookmarks, LB_ADDSTRING, 0, (LPARAM) s[i].z()); } void AppUi::setToolVisible(int m, bool vis) { if (m == 1) { ShowWindow(hBookmarks, vis ? SW_SHOW : SW_HIDE); CheckMenuItem(hMenuBar, actionId("toggle_bookmarks"), vis ? MF_CHECKED : MF_UNCHECKED); } else if (m == 2) { ShowWindow(hNotes, vis ? SW_SHOW : SW_HIDE); CheckMenuItem(hMenuBar, actionId("toggle_notes"), vis ? MF_CHECKED : MF_UNCHECKED); } } static void clearMenu(HMENU h) { for (int i = GetMenuItemCount(h) - 1; i >= 0; --i) DeleteMenu(h, i, MF_BYPOSITION); } void AppUi::populateTextStyleMenu() { AttributeSeq seq; iCascade->allNames(ETextStyle, seq); clearMenu(iTextStyleMenu); int check = 0; for (uint i = 0; i < seq.size(); ++i) { String s = seq[i].string(); AppendMenu(iTextStyleMenu, MF_STRING, TEXT_STYLE_BASE + i, s.z()); if (s == iAll.iTextStyle.string()) check = i; } CheckMenuRadioItem(iTextStyleMenu, TEXT_STYLE_BASE, TEXT_STYLE_BASE + seq.size() - 1, TEXT_STYLE_BASE + check, MF_BYCOMMAND); } void AppUi::populateLayerMenus() { clearMenu(iSelectLayerMenu); clearMenu(iMoveToLayerMenu); /* TODO for (int i = 0; i < iLayerList->count(); ++i) { QAction *a = new QAction(iLayerList->item(i)->text(), iSelectLayerMenu); QAction *a = new QAction(iLayerList->item(i)->text(), iMoveToLayerMenu); } */ } int AppUi::findAction(const char *name) const { for (int i = 0; i < int(iActions.size()); ++i) { if (iActions[i].name == name) return i; } return -1; } int AppUi::iconId(const char *name) const { int i = findAction(name); if (i >= 0 && iActions[i].icon >= 0) return iActions[i].icon; else return I_IMAGENONE; } int AppUi::actionId(const char *name) const { int i = findAction(name); return (i >= 0) ? i + IDBASE : 0; } void AppUi::cmd(int id, int notification) { ipeDebug("WM_COMMAND %d %d", id, notification); if (id == IDC_BOOKMARK && notification == LBN_SELCHANGE) luaBookmarkSelected(ListBox_GetCurSel(hBookmarks)); else if (ID_ABSOLUTE_BASE <= id && id <= ID_ABSOLUTE_BASE + EUiPageMarked) luaAbsoluteButton(selectorNames[id - ID_ABSOLUTE_BASE]); else if (ID_SELECTOR_BASE <= id && id <= ID_SELECTOR_BASE + EUiAngleSize) { int sel = id - ID_SELECTOR_BASE; int idx = SendMessage(hSelector[sel], CB_GETCURSEL, 0, 0); luaSelector(String(selectorNames[sel]), iComboContents[sel][idx]); } else if (id == ID_PATHVIEW) { luaShowPathStylePopup(Vector(iPathView->popupPos().x, iPathView->popupPos().y)); } else if (id == ID_PATHVIEW+1) { action(iPathView->action()); } else if (IDBASE <= id && id < IDBASE + int(iActions.size())) action(iActions[id - IDBASE].name); else ipeDebug("Unknown cmd %d", id); } static const char * const aboutText = "Ipe %d.%d.%d\n\n" "Copyright (c) 1993-2012 Otfried Cheong\n\n" "The extensible drawing editor Ipe creates figures " "in Postscript and PDF format, " "using LaTeX to format the text in the figures.\n" "Ipe relies on the following fine pieces of software:\n\n" " * Pdflatex\n" " * %s (%d kB used)\n" // Lua " * The font rendering library %s\n" " * The rendering library Cairo %s / %s\n" " * The compression library zlib %s\n" " * Some code from Xpdf\n\n" "Ipe is released under the GNU Public License.\n" "See ipe7.sourceforge.net for details."; void AppUi::aboutIpe() { int luaSize = lua_gc(L, LUA_GCCOUNT, 0); std::vector buf(strlen(aboutText) + 100); sprintf(&buf[0], aboutText, IPELIB_VERSION / 10000, (IPELIB_VERSION / 100) % 100, IPELIB_VERSION % 100, LUA_RELEASE, luaSize, Fonts::freetypeVersion().z(), CAIRO_VERSION_STRING, cairo_version_string(), ZLIB_VERSION); MessageBox(hwnd, &buf[0], "About Ipe", MB_OK | MB_ICONINFORMATION | MB_APPLMODAL); } void AppUi::toggleVisibility(String action, HWND h) { bool vis = IsWindowVisible(h); ShowWindow(h, vis ? SW_HIDE : SW_SHOW); int idx = actionId(action.z()); CheckMenuItem(hMenuBar, idx, vis ? MF_UNCHECKED : MF_CHECKED); layoutChildren(); } void AppUi::action(String name) { ipeDebug("action %s", name.z()); int id = actionId(name.z()); if (name == "toggle_notes") toggleVisibility(name, hNotes); else if (name == "toggle_bookmarks") toggleVisibility(name, hBookmarks); else if (name == "about") aboutIpe(); else if (name == "shift_key") { if (iCanvas) { int mod = 0; if (GetMenuState(hMenuBar, id, MF_CHECKED)) mod |= CanvasBase::EShift; iCanvas->setAdditionalModifiers(mod); } } else { // Implement radio buttons int i = name.find("|"); if (i >= 0) setCheckMark(name.left(i+1), name.substr(i+1)); if (name.left(5) == "mode_") setCheckMark("mode_", name.substr(5)); if (name.left(4) == "snap" || name == "grid_visible") setActionState(name.z(), !GetMenuState(hMenuBar, id, MF_CHECKED)); luaAction(name); } } WINID AppUi::windowId() { return hwnd; } void AppUi::setWindowCaption(bool mod, const char *s) { ipeDebug("setWindowCaption %d %s", mod, s); SetWindowText(hwnd, s); } void AppUi::showWindow(int width, int height) { ShowWindow(hwnd, win_nCmdShow); UpdateWindow(hwnd); } // show for t milliseconds, or permanently if t == 0 void AppUi::explain(const char *s, int t) { if (t) SetTimer(hwnd, ID_STATUS_TIMER, t, NULL); else KillTimer(hwnd, ID_STATUS_TIMER); SendMessage(hStatusBar, SB_SETTEXT, 0, (LPARAM) s); } void AppUi::setMouseIndicator(const char *s) { SendMessage(hStatusBar, SB_SETTEXT, 1, (LPARAM) s); } void AppUi::setZoom(double zoom) { char s[32]; sprintf(s, "(%dppi)", int(72.0 * zoom)); iCanvas->setZoom(zoom); SendMessage(hStatusBar, SB_SETTEXT, 2, (LPARAM) s); } // -------------------------------------------------------------------- struct WindowCounter { int count; HWND hwnd; }; BOOL CALLBACK AppUi::enumThreadWndProc(HWND hwnd, LPARAM lParam) { WindowCounter *wc = (WindowCounter *) lParam; // ipeDebug("Enumerating Window %d", int(hwnd)); char cname[100]; if (GetClassName(hwnd, cname, 100) && !strcmp(cname, className) && wc->hwnd != hwnd) wc->count += 1; return TRUE; } LRESULT CALLBACK AppUi::wndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) { AppUi *ui = (AppUi*) GetWindowLongPtr(hwnd, GWLP_USERDATA); switch (message) { case WM_CREATE: { LPCREATESTRUCT p = (LPCREATESTRUCT) lParam; ui = (AppUi *) p->lpCreateParams; ui->hwnd = hwnd; SetWindowLongPtr(hwnd, GWLP_USERDATA, (LONG_PTR) ui); ui->initUi(); } break; case WM_INITMENUPOPUP: if (ui) { ipeDebug("menupopup %d", lParam); if (lParam == 2) ui->populateTextStyleMenu(); else if (lParam == 6) ui->populateLayerMenus(); } break; case WM_COMMAND: if (ui) ui->cmd(LOWORD(wParam), HIWORD(wParam)); break; case WM_CTLCOLORSTATIC: if (ui && ui->iCanvas && HWND(lParam) == ui->hNotes) return (INT_PTR) (HBRUSH) GetStockObject(WHITE_BRUSH); break; case WM_SETFOCUS: if (ui && ui->iCanvas) SetFocus(ui->hwndCanvas); return 0; case WM_TIMER: if (ui && ui->iCanvas) SendMessage(ui->hStatusBar, SB_SETTEXT, 0, (LPARAM) 0); return 0; case WM_SIZE: if (ui && ui->iCanvas) ui->layoutChildren(); break; case WM_CLOSE: if (ui) { ui->closeRequested(); return 0; // do NOT allow default procedure to close } break; case WM_DESTROY: { delete ui; // only post quit message when this was the last window WindowCounter wc; wc.count = 0; wc.hwnd = hwnd; EnumThreadWindows(GetCurrentThreadId(), enumThreadWndProc, (LPARAM) &wc); if (wc.count == 0) PostQuitMessage(0); } break; default: break; } return DefWindowProc(hwnd, message, wParam, lParam); } // -------------------------------------------------------------------- void AppUi::init(HINSTANCE hInstance) { WNDCLASSEX wc; wc.cbSize = sizeof(WNDCLASSEX); wc.style = 0; wc.lpfnWndProc = wndProc; wc.cbClsExtra = 0; wc.cbWndExtra = 0; wc.hInstance = hInstance; wc.hCursor = LoadCursor(NULL, IDC_ARROW); wc.hbrBackground = (HBRUSH)(COLOR_BTNFACE+1); wc.lpszMenuName = NULL; wc.lpszClassName = className; wc.hIcon = LoadIcon(GetModuleHandle(NULL), MAKEINTRESOURCE(IDI_MYICON)); wc.hIconSm = HICON(LoadImage(GetModuleHandle(NULL), MAKEINTRESOURCE(IDI_MYICON), IMAGE_ICON, 16, 16, 0)); if (!RegisterClassEx(&wc)) { MessageBox(NULL, "AppUi registration failed!", "Error!", MB_ICONEXCLAMATION | MB_OK); exit(9); } } AppUiBase *createAppUi(lua_State *L0, int model) { return new AppUi(L0, model); } void ipe_init_appui(HINSTANCE hInstance, int nCmdShow) { AppUi::init(hInstance); PathView::init(hInstance); // save for later use win_hInstance = hInstance; win_nCmdShow = nCmdShow; } // -------------------------------------------------------------------- ipe-7.1.4/src/ipe/Makefile0000644000175000017500000000464212120621776015170 0ustar otfriedotfried# -------------------------------------------------------------------- # Makefile for Ipe # -------------------------------------------------------------------- OBJDIR = $(BUILDDIR)/obj/ipe include ../common.mak TARGET = $(call exe_target,ipe) CPPFLAGS += -I../include -I../ipecanvas -I../ipecairo -I../ipelua \ $(LUA_CFLAGS) $(UI_CFLAGS) $(CAIRO_CFLAGS) $(ZLIB_CFLAGS) LIBS += -L$(buildlib) -lipecanvas -lipecairo -lipelua -lipe -lipeui \ $(LUA_LIBS) $(UI_LIBS) $(CAIRO_LIBS) $(ZLIB_LIBS) CPPFLAGS += -DIPELETDIR=\"$(IPELETDIR)\" CPPFLAGS += -DIPELUADIR=\"$(IPELUADIR)\" CPPFLAGS += -DIPEICONDIR=\"$(IPEICONDIR)\" CPPFLAGS += -DIPEDOCDIR=\"$(IPEDOCDIR)\" CPPFLAGS += -DIPESTYLEDIR=\"$(IPESTYLEDIR)\" all: $(TARGET) sources = main.cpp tools.cpp lfs.cpp appui.cpp uilua.cpp qt_sources = appui_qt.cpp controls_qt.cpp moc_headers = appui_qt.h controls_qt.h win_sources = appui_win.cpp pathview_win.cpp gtk_sources = appui_gtk.cpp ifdef WIN32 CXXFLAGS += -mwindows LDFLAGS += -mwindows resource = $(OBJDIR)/res.o $(resource): ipe.rc $(WINDRES) -i ipe.rc -o $@ --include-dir=. else resource = endif $(TARGET): $(objects) $(resource) $(MAKE_BINDIR) $(CXX) $(LDFLAGS) -o $@ $^ $(LIBS) clean: @-rm -f $(objects) $(resource) $(TARGET) $(DEPEND) $(DEPEND): Makefile $(MAKE_DEPEND) -include $(DEPEND) install: $(TARGET) $(INSTALL_DIR) $(INSTALL_ROOT)$(IPEBINDIR) $(INSTALL_DIR) $(INSTALL_ROOT)$(IPEMANDIR) $(INSTALL_DIR) $(INSTALL_ROOT)$(IPEDOCDIR) $(INSTALL_DIR) $(INSTALL_ROOT)$(IPELUADIR) $(INSTALL_DIR) $(INSTALL_ROOT)$(IPESTYLEDIR) $(INSTALL_DIR) $(INSTALL_ROOT)$(IPESCRIPTDIR) $(INSTALL_DIR) $(INSTALL_ROOT)$(IPEICONDIR) $(INSTALL_PROGRAMS) $(TARGET) $(INSTALL_ROOT)$(IPEBINDIR) $(INSTALL_SCRIPTS) ../../scripts/* $(INSTALL_ROOT)$(IPESCRIPTDIR) $(INSTALL_FILES) ../../man/*.1 $(INSTALL_ROOT)$(IPEMANDIR) $(INSTALL_FILES) ../../build/doc/* $(INSTALL_ROOT)$(IPEDOCDIR) $(INSTALL_FILES) lua/*.lua $(INSTALL_ROOT)$(IPELUADIR) $(INSTALL_FILES) ../../styles/basic.isy $(INSTALL_ROOT)$(IPESTYLEDIR) $(INSTALL_FILES) ../../styles/colors.isy $(INSTALL_ROOT)$(IPESTYLEDIR) $(INSTALL_FILES) ../../styles/beamer.isy $(INSTALL_ROOT)$(IPESTYLEDIR) $(INSTALL_FILES) ../../styles/presentation.isy \ $(INSTALL_ROOT)$(IPESTYLEDIR) $(INSTALL_FILES) icons/*.png $(INSTALL_ROOT)$(IPEICONDIR) # -------------------------------------------------------------------- ipe-7.1.4/src/ipe/appui.cpp0000644000175000017500000005034512120621776015353 0ustar otfriedotfried// -------------------------------------------------------------------- // AppUi // -------------------------------------------------------------------- /* This file is part of the extensible drawing editor Ipe. Copyright (C) 1993-2013 Otfried Cheong Ipe is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. As a special exception, you have permission to link Ipe with the CGAL library and distribute executables, as long as you follow the requirements of the Gnu General Public License in regard to all of the software in the executable aside from CGAL. Ipe 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 General Public License for more details. You should have received a copy of the GNU General Public License along with Ipe; if not, you can find it at "http://www.gnu.org/copyleft/gpl.html", or write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ #include "appui.h" #include "tools.h" #include "ipelua.h" #include "ipecairopainter.h" using namespace ipe; using namespace ipelua; // -------------------------------------------------------------------- const char * const AppUiBase::selectorNames[] = { "stroke", "fill", "pen", "textsize", "markshape", "symbolsize", "gridsize", "anglesize", "view", "page", "viewmarked", "pagemarked" }; AppUiBase::AppUiBase(lua_State *L0, int model) { L = L0; iModel = model; iMouseIn = 0; // points iMouseFactor = 1.0; // scale 1:1 iCoordinatesFormat = "%g%s, %g%s"; lua_getglobal(L, "prefs"); lua_getfield(L, -1, "coordinates_format"); if (lua_isstring(L, -1)) { iCoordinatesFormat = lua_tostring(L, -1); } lua_pop(L, 1); // coordinates_format iScalings.push_back(1); lua_getfield(L, -1, "scale_factors"); if (lua_istable(L, -1)) { int n = lua_rawlen(L, -1); for (int i = 1; i <= n; ++i) { lua_rawgeti(L, -1, i); if (lua_isnumber(L, -1)) iScalings.push_back(lua_tointeger(L, -1)); lua_pop(L, 1); // number } } lua_pop(L, 2); // prefs, scale_factors } AppUiBase::~AppUiBase() { ipeDebug("AppUiBase C++ destructor"); luaL_unref(L, LUA_REGISTRYINDEX, iModel); // collect this model lua_gc(L, LUA_GCCOLLECT, 0); } // -------------------------------------------------------------------- void AppUiBase::buildMenus() { addRootMenu(EFileMenu, "&File"); addRootMenu(EEditMenu, "&Edit"); addRootMenu(EPropertiesMenu, "P&roperties"); addRootMenu(ESnapMenu, "&Snap"); addRootMenu(EModeMenu, "&Mode"); addRootMenu(EZoomMenu, "&Zoom"); addRootMenu(ELayerMenu, "&Layers"); addRootMenu(EViewMenu, "&Views"); addRootMenu(EPageMenu, "&Pages"); addRootMenu(EIpeletMenu, "&Ipelets"); addRootMenu(EHelpMenu, "&Help"); addItem(EFileMenu, "New Window", "new_window"); addItem(EFileMenu, "New", "new"); addItem(EFileMenu, "Open", "open"); addItem(EFileMenu, "Save", "save"); addItem(EFileMenu, "Save as", "save_as"); addItem(EFileMenu); addItem(EFileMenu, "Automatically run Latex", "*auto_latex"); addItem(EFileMenu, "Run Latex", "run_latex"); addItem(EFileMenu); addItem(EFileMenu, "Close", "close"); addItem(EFileMenu, "Exit", "quit"); addItem(EEditMenu, "Undo", "undo"); addItem(EEditMenu, "Redo", "redo"); addItem(EEditMenu); addItem(EEditMenu, "Cut", "cut"); addItem(EEditMenu, "Copy", "copy"); addItem(EEditMenu, "Paste", "paste"); addItem(EEditMenu, "Paste at cursor", "paste_at_cursor"); addItem(EEditMenu, "Delete", "delete"); addItem(EEditMenu); addItem(EEditMenu, "Group", "group"); addItem(EEditMenu, "Ungroup", "ungroup"); addItem(EEditMenu, "Front", "front"); addItem(EEditMenu, "Back", "back"); addItem(EEditMenu, "Forward", "forward"); addItem(EEditMenu, "Backward", "backward"); addItem(EEditMenu, "Just before", "before"); addItem(EEditMenu, "Just behind", "behind"); addItem(EEditMenu, "Duplicate", "duplicate"); addItem(EEditMenu, "Select all", "select_all"); addItem(EEditMenu); addItem(EEditMenu, "Insert text box", "insert_text_box"); addItem(EEditMenu, "Edit object", "edit"); addItem(EEditMenu, "Edit object as XML", "edit_as_xml"); addItem(EEditMenu, "Change text width", "change_width"); addItem(EEditMenu); addItem(EEditMenu, "Document properties", "document_properties"); addItem(EEditMenu, "Style sheets", "style_sheets"); addItem(EEditMenu, "Update style sheets", "update_style_sheets"); addItem(EEditMenu, "Check symbolic attributes", "check_style"); startSubMenu(EPropertiesMenu, "Pinned"); addSubItem("none", "pinned|none"); addSubItem("horizontal", "pinned|horizontal"); addSubItem("vertical", "pinned|vertical"); addSubItem("fixed", "pinned|fixed"); endSubMenu(); startSubMenu(EPropertiesMenu, "Transformations"); addSubItem("translations", "transformations|translations"); addSubItem("rigid motions", "transformations|rigid"); addSubItem("affine", "transformations|affine"); endSubMenu(); addItem(EPropertiesMenu); startSubMenu(EPropertiesMenu, "Text style"); iTextStyleMenu = endSubMenu(); startSubMenu(EPropertiesMenu, "Horizontal alignment"); addSubItem("left", "horizontalalignment|left"); addSubItem("center", "horizontalalignment|hcenter"); addSubItem("right", "horizontalalignment|right"); endSubMenu(); startSubMenu(EPropertiesMenu, "Vertical alignment"); addSubItem("bottom", "verticalalignment|bottom"); addSubItem("baseline", "verticalalignment|baseline"); addSubItem("center", "verticalalignment|vcenter"); addSubItem("top", "verticalalignment|top"); endSubMenu(); startSubMenu(EPropertiesMenu, "Transformable text"); addSubItem("Yes", "transformabletext|true"); addSubItem("No", "transformabletext|false"); endSubMenu(); addItem(EModeMenu, "Select objects (with Shift: non-destructive)", "mode_select"); addItem(EModeMenu, "Translate objects (with Shift: horizontal/vertical)", "mode_translate"); addItem(EModeMenu, "Rotate objects", "mode_rotate"); addItem(EModeMenu, "Stretch objects (with Shift: scale objects)", "mode_stretch"); addItem(EModeMenu, "Pan the canvas", "mode_pan"); addItem(EModeMenu, "Shred objects", "mode_shredder"); addItem(EModeMenu); // TODO iObjectTools->addSeparator(); addItem(EModeMenu, "Text labels", "mode_label"); addItem(EModeMenu, "Mathematical symbols", "mode_math"); addItem(EModeMenu, "Paragraphs", "mode_paragraph"); addItem(EModeMenu, "Marks", "mode_marks"); addItem(EModeMenu, "Rectangles (with Shift: squares)", "mode_rectangles"); addItem(EModeMenu, "Lines and polylines", "mode_lines"); addItem(EModeMenu, "Polygons", "mode_polygons"); addItem(EModeMenu, "Splines", "mode_splines"); addItem(EModeMenu, "Splinegons", "mode_splinegons"); addItem(EModeMenu, "Circular arcs (by center, right and left point)", "mode_arc1"); addItem(EModeMenu, "Circular arcs (by center, left and right point)", "mode_arc2"); addItem(EModeMenu, "Circular arcs (by 3 points)", "mode_arc3"); addItem(EModeMenu, "Circles (by center and radius)", "mode_circle1"); addItem(EModeMenu, "Circles (by diameter)", "mode_circle2"); addItem(EModeMenu, "Circles (by 3 points)", "mode_circle3"); addItem(EModeMenu, "Ink", "mode_ink"); addItem(ESnapMenu, "Snap to vertex", "@snapvtx"); addItem(ESnapMenu, "Snap to boundary", "@snapbd"); addItem(ESnapMenu, "Snap to intersection", "@snapint"); addItem(ESnapMenu, "Snap to grid", "@snapgrid"); addItem(ESnapMenu, "Angular snap", "@snapangle"); addItem(ESnapMenu, "Automatic snap", "@snapauto"); addItem(ESnapMenu); addItem(ESnapMenu, "Set origin && snap", "@set_origin_snap"); addItem(ESnapMenu, "Hide axes", "@hide_axes"); addItem(ESnapMenu, "Set direction", "@set_direction"); addItem(ESnapMenu, "Reset direction", "@reset_direction"); addItem(ESnapMenu, "Set line", "@set_line"); addItem(ESnapMenu, "Set line && snap", "@set_line_snap"); #ifndef IPEUI_WIN32 addItem(EZoomMenu, "Fullscreen", "@*fullscreen"); #endif addItem(EZoomMenu, "Grid visible", "@*grid_visible"); startSubMenu(EZoomMenu, "Coordinates"); addSubItem("points", "@coordinates|points"); addSubItem("mm", "@coordinates|mm"); addSubItem("m", "@coordinates|m"); addSubItem("inch", "@coordinates|inch"); endSubMenu(); startSubMenu(EZoomMenu, "Coordinate scale"); for (uint i = 0; i < iScalings.size(); ++i) { char display[32]; char action[32]; int s = iScalings[i]; if (s < 0) sprintf(display, "%d:1", -s); else sprintf(display, "1:%d", s); sprintf(action, "@scaling|%d", s); addSubItem(display, action); } endSubMenu(); addItem(EZoomMenu); addItem(EZoomMenu, "Zoom in", "@zoom_in"); addItem(EZoomMenu, "Zoom out", "@zoom_out"); addItem(EZoomMenu, "Normal size", "@normal_size"); addItem(EZoomMenu, "Fit page", "@fit_page"); addItem(EZoomMenu, "Fit width", "@fit_width"); addItem(EZoomMenu, "Fit page top", "@fit_top"); addItem(EZoomMenu, "Fit objects", "@fit_objects"); addItem(EZoomMenu, "Fit selection", "@fit_selection"); addItem(EZoomMenu); addItem(EZoomMenu, "Pan here", "@pan_here"); addItem(ELayerMenu, "New layer", "new_layer"); addItem(ELayerMenu, "Rename active layer", "rename_active_layer"); addItem(ELayerMenu); addItem(ELayerMenu, "Select all in active layer", "select_in_active_layer"); startSubMenu(ELayerMenu, "Select all in layer"); iSelectLayerMenu = endSubMenu(); addItem(ELayerMenu, "Move to active layer", "move_to_active_layer"); startSubMenu(ELayerMenu, "Move to layer"); iMoveToLayerMenu = endSubMenu(); addItem(EViewMenu, "Next view", "next_view"); addItem(EViewMenu, "Previous view", "previous_view"); addItem(EViewMenu, "First view", "first_view"); addItem(EViewMenu, "Last view", "last_view"); addItem(EViewMenu); addItem(EViewMenu, "New layer, new view", "new_layer_view"); addItem(EViewMenu, "New view", "new_view"); addItem(EViewMenu, "Delete view", "delete_view"); addItem(EViewMenu); addItem(EViewMenu, "Jump to view", "jump_view"); addItem(EViewMenu, "Edit effects", "edit_effects"); addItem(EPageMenu, "Next page", "next_page"); addItem(EPageMenu, "Previous page", "previous_page"); addItem(EPageMenu, "First page", "first_page"); addItem(EPageMenu, "Last page", "last_page"); addItem(EPageMenu); addItem(EPageMenu, "New page", "new_page"); addItem(EPageMenu, "Cut page", "cut_page"); addItem(EPageMenu, "Copy page", "copy_page"); addItem(EPageMenu, "Paste page", "paste_page"); addItem(EPageMenu, "Delete page", "delete_page"); addItem(EPageMenu); addItem(EPageMenu, "Jump to page", "jump_page"); addItem(EPageMenu, "Edit title && sections", "edit_title"); addItem(EPageMenu, "Edit notes", "edit_notes"); addItem(EPageMenu, "Page sorter", "page_sorter"); addItem(EPageMenu); #ifdef IPEUI_WIN32 addItem(EPageMenu, "Notes", "toggle_notes"); addItem(EPageMenu, "Bookmarks", "toggle_bookmarks"); #endif addItem(EHelpMenu, "Ipe &manual", "manual"); addItem(EHelpMenu, "Onscreen keyboard", "@keyboard"); addItem(EHelpMenu, "Show &configuration", "show_configuration"); addItem(EHelpMenu, "About the &ipelets", "about_ipelets"); addItem(EHelpMenu, "&About Ipe", "about"); // build Ipelet menu lua_getglobal(L, "ipelets"); int n = lua_rawlen(L, -1); for (int i = 1; i <= n; ++i) { lua_rawgeti(L, -1, i); lua_getfield(L, -1, "label"); String label(lua_tostring(L, -1)); lua_pop(L, 1); lua_getfield(L, -1, "name"); String name(lua_tostring(L, -1)); lua_pop(L, 1); lua_getfield(L, -1, "methods"); char buf[20]; if (lua_isnil(L, -1)) { String action("ipelet_1_"); action += name; addItem(EIpeletMenu, label.z(), action.z()); } else { int m = lua_rawlen(L, -1); startSubMenu(EIpeletMenu, label.z()); for (int j = 1; j <= m; ++j) { lua_rawgeti(L, -1, j); lua_getfield(L, -1, "label"); sprintf(buf, "ipelet_%d_", j); String action(buf); action += name; addSubItem(lua_tostring(L, -1), action.z()); lua_pop(L, 2); // sublabel, method } endSubMenu(); } lua_pop(L, 2); // methods, ipelet } lua_pop(L, 1); } // -------------------------------------------------------------------- void AppUiBase::canvasObserverWheelMoved(int degrees) { if (degrees > 0) action("wheel_zoom_in"); else action("wheel_zoom_out"); } void AppUiBase::canvasObserverToolChanged(bool hasTool) { setActionsEnabled(!hasTool); } static void adjust(double &x, int mode, double factor) { if (ipe::abs(x) < 1e-12) x = 0.0; x *= factor; switch (mode) { case 1: // mm x = (x / 72.0) * 25.4; break; case 2: // m x = (x / 72000.0) * 25.4; break; case 3: // in x /= 72; break; default: break; } } static const char * const mouse_units[] = { "", " mm", " m", " in" }; void AppUiBase::canvasObserverPositionChanged() { Vector v = iCanvas->CanvasBase::pos(); const Snap &snap = iCanvas->snap(); if (snap.iWithAxes) { v = v - snap.iOrigin; v = Linear(-snap.iDir) * v; } adjust(v.x, iMouseIn, iMouseFactor); adjust(v.y, iMouseIn, iMouseFactor); const char *units = mouse_units[iMouseIn]; char s[32]; sprintf(s, iCoordinatesFormat.z(), v.x, units, v.y, units); setMouseIndicator(s); } void AppUiBase::canvasObserverMouseAction(int button) { lua_rawgeti(L, LUA_REGISTRYINDEX, iModel); lua_getfield(L, -1, "mouseButtonAction"); lua_insert(L, -2); // model push_button(L, button); lua_call(L, 3, 0); } void AppUiBase::canvasObserverSizeChanged() { lua_rawgeti(L, LUA_REGISTRYINDEX, iModel); lua_getfield(L, -1, "sizeChanged"); lua_insert(L, -2); // model lua_call(L, 1, 0); } // -------------------------------------------------------------------- static void call_selector(lua_State *L, int model, String name) { // calls model selector lua_rawgeti(L, LUA_REGISTRYINDEX, model); lua_getfield(L, -1, "selector"); lua_pushvalue(L, -2); // model lua_remove(L, -3); push_string(L, name); } void AppUiBase::luaSelector(String name, String value) { call_selector(L, iModel, name); if (value == "true") lua_pushboolean(L, true); else if (value == "false") lua_pushboolean(L, false); else push_string(L, value); lua_call(L, 3, 0); } void AppUiBase::luaAbsoluteButton(const char *s) { // calls model selector lua_rawgeti(L, LUA_REGISTRYINDEX, iModel); lua_getfield(L, -1, "absoluteButton"); lua_insert(L, -2); // method, model lua_pushstring(L, s); lua_call(L, 2, 0); } // -------------------------------------------------------------------- void AppUiBase::luaAction(String name) { if (name.left(12) == "coordinates|") { if (name.right(2) == "mm") iMouseIn = 1; else if (name.right(1) == "m") iMouseIn = 2; else if (name.right(4) == "inch") iMouseIn = 3; else iMouseIn = 0; } else if (name.left(8) == "scaling|") { Lex lex(name.substr(8)); int s = lex.getInt(); if (s < 0) iMouseFactor = 1.0 / -s; else iMouseFactor = s; } else if (name.find('|') >= 0) { // calls model selector int i = name.find('|'); luaSelector(name.left(i), name.substr(i+1)); } else { // calls model action lua_rawgeti(L, LUA_REGISTRYINDEX, iModel); lua_getfield(L, -1, "action"); lua_insert(L, -2); // before model push_string(L, name); lua_call(L, 2, 0); } } void AppUiBase::luaShowPathStylePopup(Vector v) { lua_rawgeti(L, LUA_REGISTRYINDEX, iModel); lua_getfield(L, -1, "showPathStylePopup"); lua_insert(L, -2); // before model push_vector(L, v); lua_call(L, 2, 0); } void AppUiBase::luaShowLayerBoxPopup(Vector v, String layer) { lua_rawgeti(L, LUA_REGISTRYINDEX, iModel); lua_getfield(L, -1, "showLayerBoxPopup"); lua_insert(L, -2); // before model push_vector(L, v); push_string(L, layer); lua_call(L, 3, 0); } void AppUiBase::luaLayerAction(String name, String layer) { lua_rawgeti(L, LUA_REGISTRYINDEX, iModel); lua_getfield(L, -1, "layerAction"); lua_insert(L, -2); // before model push_string(L, name); push_string(L, layer); lua_call(L, 3, 0); } void AppUiBase::luaBookmarkSelected(int index) { lua_rawgeti(L, LUA_REGISTRYINDEX, iModel); lua_getfield(L, -1, "bookmark"); lua_insert(L, -2); // method, model lua_pushnumber(L, index + 1); lua_call(L, 2, 0); } // -------------------------------------------------------------------- static String stripMark(Attribute mark) { String s = mark.string(); if (s.left(5) == "mark/") { int i = s.rfind('('); return s.substr(5, i > 0 ? i-5 : -1); } else return String(); } void AppUiBase::showInCombo(const Cascade *sheet, Kind kind, int sel, const char *deflt) { AttributeSeq seq; sheet->allNames(kind, seq); if (!seq.size() && deflt != 0) { addCombo(sel, deflt); iComboContents[sel].push_back(deflt); } for (uint i = 0; i < seq.size(); ++i) { String s = seq[i].string(); addCombo(sel, s); iComboContents[sel].push_back(s); } } void AppUiBase::showMarksInCombo(const Cascade *sheet) { AttributeSeq seq; sheet->allNames(ESymbol, seq); for (uint i = 0; i < seq.size(); ++i) { String s = stripMark(seq[i]); if (!s.isEmpty()) { addCombo(EUiMarkShape, s); iComboContents[EUiMarkShape].push_back(s); } } } void AppUiBase::setupSymbolicNames(const Cascade *sheet) { resetCombos(); for (int i = 0; i < EUiView; ++i) iComboContents[i].clear(); AttributeSeq seq; sheet->allNames(EColor, seq); for (uint i = 0; i < seq.size(); ++i) { Attribute abs = sheet->find(EColor, seq[i]); Color color = abs.color(); String s = seq[i].string(); addComboColor(EUiStroke, s, color); addComboColor(EUiFill, s, color); iComboContents[EUiStroke].push_back(s); iComboContents[EUiFill].push_back(s); } showInCombo(sheet, EPen, EUiPen); showInCombo(sheet, ETextSize, EUiTextSize); showInCombo(sheet, ESymbolSize, EUiSymbolSize); showMarksInCombo(sheet); showInCombo(sheet, EGridSize, EUiGridSize, "16pt"); showInCombo(sheet, EAngleSize, EUiAngleSize, "45 deg"); } void AppUiBase::setGridAngleSize(Attribute abs_grid, Attribute abs_angle) { AttributeSeq seq; iCascade->allNames(EGridSize, seq); for (uint i = 0; i < seq.size(); ++i) { if (iCascade->find(EGridSize, seq[i]) == abs_grid) { setComboCurrent(EUiGridSize, i); break; } } seq.clear(); iCascade->allNames(EAngleSize, seq); for (uint i = 0; i < seq.size(); ++i) { if (iCascade->find(EAngleSize, seq[i]) == abs_angle) { setComboCurrent(EUiAngleSize, i); break; } } } // -------------------------------------------------------------------- void AppUiBase::setAttribute(int sel, Attribute a) { String s = a.string(); for (int i = 0; i < int(iComboContents[sel].size()); ++i) { if (iComboContents[sel][i] == s) { setComboCurrent(sel, i); return; } } } void AppUiBase::setAttributes(const AllAttributes &all, Cascade *sheet) { iAll = all; iCascade = sheet; setPathView(all, sheet); setAttribute(EUiStroke, iAll.iStroke); setAttribute(EUiFill, iAll.iFill); Color stroke = iCascade->find(EColor, iAll.iStroke).color(); Color fill = iCascade->find(EColor, iAll.iFill).color(); setButtonColor(EUiStroke, stroke); setButtonColor(EUiFill, fill); // iButton[]->setIcon(prefsColorIcon(stroke)); setAttribute(EUiPen, iAll.iPen); setAttribute(EUiTextSize, iAll.iTextSize); setAttribute(EUiSymbolSize, iAll.iSymbolSize); String s = stripMark(iAll.iMarkShape); for (int i = 0; i < int(iComboContents[EUiMarkShape].size()); ++i) { if (iComboContents[EUiMarkShape][i] == s) { setComboCurrent(EUiMarkShape, i); break; } } setCheckMark("horizontalalignment", Attribute(iAll.iHorizontalAlignment)); setCheckMark("verticalalignment", Attribute(iAll.iVerticalAlignment)); setCheckMark("pinned", Attribute(iAll.iPinned)); setCheckMark("transformabletext", Attribute::Boolean(iAll.iTransformableText)); setCheckMark("transformations", Attribute(iAll.iTransformations)); setCheckMark("linejoin", Attribute(iAll.iLineJoin)); setCheckMark("linecap", Attribute(iAll.iLineCap)); setCheckMark("fillrule", Attribute(iAll.iFillRule)); } // -------------------------------------------------------------------- ipe-7.1.4/src/ipe/appui.h0000644000175000017500000001327312120621776015017 0ustar otfriedotfried// -*- C++ -*- // -------------------------------------------------------------------- // Appui // -------------------------------------------------------------------- /* This file is part of the extensible drawing editor Ipe. Copyright (C) 1993-2013 Otfried Cheong Ipe is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. As a special exception, you have permission to link Ipe with the CGAL library and distribute executables, as long as you follow the requirements of the Gnu General Public License in regard to all of the software in the executable aside from CGAL. Ipe 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 General Public License for more details. You should have received a copy of the GNU General Public License along with Ipe; if not, you can find it at "http://www.gnu.org/copyleft/gpl.html", or write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ #ifndef APPUI_H #define APPUI_H #include "ipecanvas.h" using namespace ipe; // avoid including Lua headers here typedef struct lua_State lua_State; #ifdef IPEUI_GTK #include typedef GtkWidget *WINID; typedef GtkMenu *MENUHANDLE; #endif #ifdef IPEUI_WIN32 #define _WIN32_WINNT 0x0501 #define _WIN32_IE 0x0501 #include #include typedef HWND WINID; typedef HMENU MENUHANDLE; #endif #ifdef IPEUI_QT #include #include typedef QWidget *WINID; typedef QMenu *MENUHANDLE; #endif class AppUiBase; extern WINID check_winid(lua_State *L, int i); extern void push_winid(lua_State *L, WINID win); extern String ipeIconDirectory(); extern AppUiBase *createAppUi(lua_State *L0, int model); // -------------------------------------------------------------------- class AppUiBase : public CanvasObserver { public: enum { EFileMenu, EEditMenu, EPropertiesMenu, ESnapMenu, EModeMenu, EZoomMenu, ELayerMenu, EViewMenu, EPageMenu, EIpeletMenu, EHelpMenu, ENumMenu }; // change list selectorNames if enum changes enum { EUiStroke, EUiFill, EUiPen, EUiTextSize, EUiMarkShape, EUiSymbolSize, EUiGridSize, EUiAngleSize, EUiView, EUiPage, EUiViewMarked, EUiPageMarked }; public: virtual ~AppUiBase(); CanvasBase *canvas() { return iCanvas; } void setupSymbolicNames(const Cascade *sheet); void setGridAngleSize(Attribute abs_grid, Attribute abs_angle); void setAttributes(const AllAttributes &all, Cascade *sheet); public: // What platforms must implement: virtual WINID windowId() = 0; virtual int actionId(const char *name) const = 0; virtual void closeWindow() = 0; virtual bool actionState(const char *name) = 0; virtual void setActionState(const char *name, bool value) = 0; virtual void setNumbers(String vno, bool vm, String pno, bool pm) = 0; virtual void setLayers(const Page *page, int view) = 0; virtual void setZoom(double zoom) = 0; virtual void setWindowCaption(bool mod, const char *s) = 0; virtual void setNotes(String notes) = 0; virtual void explain(const char *s, int t) = 0; virtual void showWindow(int width, int height) = 0; virtual void action(String name) = 0; virtual void setActionsEnabled(bool mode) = 0; virtual void setMouseIndicator(const char *s) = 0; virtual void setBookmarks(int no, const String *s) = 0; virtual void setToolVisible(int m, bool vis) = 0; protected: // What platforms must implement: virtual void addRootMenu(int id, const char *name) = 0; // if title == 0, add separator virtual void addItem(int id, const char *title = 0, const char *name = 0) = 0; virtual void startSubMenu(int id, const char *name) = 0; virtual void addSubItem(const char *title, const char *name) = 0; virtual MENUHANDLE endSubMenu() = 0; virtual void addCombo(int sel, String s) = 0; virtual void resetCombos() = 0; virtual void addComboColor(int sel, String s, Color color) = 0; virtual void setComboCurrent(int sel, int idx) = 0; virtual void setPathView(const AllAttributes &all, Cascade *sheet) = 0; virtual void setCheckMark(String name, Attribute a) = 0; virtual void setButtonColor(int sel, Color color) = 0; protected: virtual void canvasObserverWheelMoved(int degrees); virtual void canvasObserverMouseAction(int button); virtual void canvasObserverPositionChanged(); virtual void canvasObserverToolChanged(bool hasTool); virtual void canvasObserverSizeChanged(); protected: AppUiBase(lua_State *L0, int model); static const char * const selectorNames[]; void luaSelector(String name, String value); void luaAction(String name); void luaShowPathStylePopup(Vector v); void luaShowLayerBoxPopup(Vector v, String layer); void luaLayerAction(String name, String layer); void luaAbsoluteButton(const char *s); void luaBookmarkSelected(int index); void buildMenus(); void showInCombo(const Cascade *sheet, Kind kind, int sel, const char *deflt = 0); void showMarksInCombo(const Cascade *sheet); void setAttribute(int sel, Attribute a); protected: lua_State *L; int iModel; // reference to Lua model MENUHANDLE iSelectLayerMenu; MENUHANDLE iMoveToLayerMenu; MENUHANDLE iTextStyleMenu; Cascade *iCascade; AllAttributes iAll; // current settings in UI std::vector iComboContents[EUiView]; CanvasBase *iCanvas; std::vector iScalings; String iCoordinatesFormat; int iMouseIn; double iMouseFactor; }; // -------------------------------------------------------------------- #endif ipe-7.1.4/src/ipe/appui_win.h0000644000175000017500000001073512120621776015674 0ustar otfriedotfried// -*- C++ -*- // -------------------------------------------------------------------- // Appui for Win32 // -------------------------------------------------------------------- /* This file is part of the extensible drawing editor Ipe. Copyright (C) 1993-2013 Otfried Cheong Ipe is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. As a special exception, you have permission to link Ipe with the CGAL library and distribute executables, as long as you follow the requirements of the Gnu General Public License in regard to all of the software in the executable aside from CGAL. Ipe 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 General Public License for more details. You should have received a copy of the GNU General Public License along with Ipe; if not, you can find it at "http://www.gnu.org/copyleft/gpl.html", or write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ #ifndef APPUI_WIN_H #define APPUI_WIN_H #include "appui.h" class PathView; using namespace ipe; // -------------------------------------------------------------------- class AppUi : public AppUiBase { public: static void init(HINSTANCE hInstance); AppUi(lua_State *L0, int model); ~AppUi(); virtual void action(String name); virtual void setLayers(const Page *page, int view); virtual void setZoom(double zoom); virtual void setActionsEnabled(bool mode); virtual void setNumbers(String vno, bool vm, String pno, bool pm); virtual void setNotes(String notes); virtual int actionId(const char *name) const; virtual WINID windowId(); virtual void closeWindow(); virtual bool actionState(const char *name); virtual void setActionState(const char *name, bool value); virtual void setWindowCaption(bool mod, const char *s); virtual void explain(const char *s, int t); virtual void showWindow(int width, int height); virtual void setBookmarks(int no, const String *s); virtual void setToolVisible(int m, bool vis); private: void initUi(); void layoutChildren(); void createAction(String name, String tooltip, bool canWhileDrawing = false); int findAction(const char *name) const; void addItem(HMENU menu, const char *title, const char *name); virtual void addRootMenu(int id, const char *name); virtual void addItem(int id, const char *title, const char *name); virtual void startSubMenu(int id, const char *name); virtual void addSubItem(const char *title, const char *name); virtual MENUHANDLE endSubMenu(); virtual void setMouseIndicator(const char *s); virtual void addCombo(int sel, String s); virtual void resetCombos(); virtual void addComboColor(int sel, String s, Color color); virtual void setComboCurrent(int sel, int idx); virtual void setCheckMark(String name, Attribute a); virtual void setPathView(const AllAttributes &all, Cascade *sheet); virtual void setButtonColor(int sel, Color color); void populateTextStyleMenu(); void populateLayerMenus(); void cmd(int id, int notification); void setCheckMark(String name, String value); void aboutIpe(); void closeRequested(); int iconId(const char *name) const; void addTButton(HWND tb, const char *name = 0, int flags = 0); void setTooltip(HWND h, String tip, bool isComboBoxEx = false); void toggleVisibility(String action, HWND h); HWND createButton(HINSTANCE hInst, int id, int flags = BS_BITMAP|BS_PUSHBUTTON); private: static LRESULT CALLBACK wndProc(HWND hwnd, UINT Message, WPARAM wParam, LPARAM lParam); static BOOL CALLBACK enumThreadWndProc(HWND hwnd, LPARAM lParam); static const char className[]; private: struct SAction { String name; String tooltip; int icon; bool alwaysOn; }; std::vector iActions; HMENU hMenuBar; HMENU hRootMenu[ENumMenu]; HIMAGELIST hIcons; HWND hwnd; HWND hwndCanvas; HWND hTip; HWND hStatusBar; HWND hToolBar; HWND hNotes; HWND hBookmarks; HWND hProperties; HWND hButton[EUiGridSize]; HWND hSelector[EUiView]; HWND hViewNumber; HWND hPageNumber; HWND hViewMarked; HWND hPageMarked; PathView *iPathView; }; // -------------------------------------------------------------------- #endif ipe-7.1.4/src/ipe/tools.cpp0000644000175000017500000001606212120621776015373 0ustar otfriedotfried// -------------------------------------------------------------------- // Canvas tools used from Lua // -------------------------------------------------------------------- /* This file is part of the extensible drawing editor Ipe. Copyright (C) 1993-2013 Otfried Cheong Ipe is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. As a special exception, you have permission to link Ipe with the CGAL library and distribute executables, as long as you follow the requirements of the Gnu General Public License in regard to all of the software in the executable aside from CGAL. Ipe 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 General Public License for more details. You should have received a copy of the GNU General Public License along with Ipe; if not, you can find it at "http://www.gnu.org/copyleft/gpl.html", or write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ #include "tools.h" extern "C" { #include #include #include } #include "ipecanvas.h" #include "ipepainter.h" #include "ipelua.h" using namespace ipe; using namespace ipelua; // -------------------------------------------------------------------- IpeTransformTool::IpeTransformTool(CanvasBase *canvas, Page *page, int view, TType type, bool withShift, lua_State *L0, int method) : TransformTool(canvas, page, view, type, withShift) { L = L0; iMethod = method; } IpeTransformTool::~IpeTransformTool() { luaL_unref(L, LUA_REGISTRYINDEX, iMethod); } void IpeTransformTool::report() { // call back to Lua to report final transformation lua_rawgeti(L, LUA_REGISTRYINDEX, iMethod); push_matrix(L, iTransform); lua_call(L, 1, 0); } // -------------------------------------------------------------------- static void push_modifiers(lua_State *L, int button) { lua_createtable(L, 0, 4); lua_pushboolean(L, (button & CanvasBase::EShift)); lua_setfield(L, -2, "shift"); lua_pushboolean(L, (button & CanvasBase::EControl)); lua_setfield(L, -2, "control"); lua_pushboolean(L, (button & CanvasBase::EAlt)); lua_setfield(L, -2, "alt"); lua_pushboolean(L, (button & CanvasBase::EMeta)); lua_setfield(L, -2, "meta"); } void push_button(lua_State *L, int button) { lua_pushinteger(L, (button & 0xff)); // button number push_modifiers(L, button); } // -------------------------------------------------------------------- LuaTool::LuaTool(CanvasBase *canvas, lua_State *L0, int luatool) : Tool(canvas) { L = L0; iLuaTool = luatool; iColor = Color(0, 0, 0); } LuaTool::~LuaTool() { luaL_unref(L, LUA_REGISTRYINDEX, iLuaTool); } void LuaTool::mouseButton(int button, bool press) { lua_rawgeti(L, LUA_REGISTRYINDEX, iLuaTool); lua_getfield(L, -1, "mouseButton"); lua_pushvalue(L, -2); // model lua_remove(L, -3); push_button(L, button); lua_pushboolean(L, press); lua_call(L, 4, 0); } void LuaTool::mouseMove() { lua_rawgeti(L, LUA_REGISTRYINDEX, iLuaTool); lua_getfield(L, -1, "mouseMove"); lua_pushvalue(L, -2); // model lua_remove(L, -3); lua_call(L, 1, 0); } bool LuaTool::key(int code, int modifiers, String text) { lua_rawgeti(L, LUA_REGISTRYINDEX, iLuaTool); lua_getfield(L, -1, "key"); lua_pushvalue(L, -2); // model lua_remove(L, -3); lua_pushnumber(L, code); push_modifiers(L, modifiers); push_string(L, text); lua_State *L0 = L; // need to save L since lua_call(L, 4, 1); // this may delete tool return lua_toboolean(L0, 1); } // -------------------------------------------------------------------- ShapeTool::ShapeTool(CanvasBase *canvas, lua_State *L0, int luatool) : LuaTool(canvas, L0, luatool) { iPen = 1.0; } void ShapeTool::draw(Painter &painter) const { double z = 1.0 / iCanvas->zoom(); painter.setPen(Attribute(Fixed::fromDouble(iPen))); painter.setStroke(Attribute(iColor)); painter.newPath(); iShape.draw(painter); painter.drawPath(EStrokedOnly); painter.setStroke(Attribute(Color(0, 1000, 0))); painter.setPen(Attribute(Fixed::fromDouble(1.0))); painter.newPath(); iAuxShape.draw(painter); painter.drawPath(EStrokedOnly); for (uint i = 0; i < iMarks.size(); ++i) { switch (iMarks[i].t) { case EVertex: painter.setFill(Attribute(Color(1000, 0, 1000))); break; case ECenter: case ERadius: painter.setFill(Attribute(Color(0, 0, 1000))); break; case ESplineCP: painter.setFill(Attribute(Color(0, 0, 800))); break; case EBezierCP: case EMinor: painter.setFill(Attribute(Color(0, 800, 0))); break; case ECurrent: painter.setStroke(Attribute(Color(1000, 0, 0))); break; case EScissor: painter.setFill(Attribute(Color(1000, 0, 0))); break; default: break; } painter.pushMatrix(); painter.translate(iMarks[i].v); painter.untransform(ETransformationsTranslations); switch (iMarks[i].t) { case EVertex: case ECenter: default: painter.newPath(); painter.moveTo(Vector(6*z, 0)); painter.drawArc(Arc(Matrix(6*z, 0, 0, 6*z, 0, 0))); painter.closePath(); painter.drawPath(EFilledOnly); break; case ECurrent: painter.newPath(); painter.moveTo(Vector(9*z, 0)); painter.drawArc(Arc(Matrix(9*z, 0, 0, 9*z, 0, 0))); painter.closePath(); painter.drawPath(EStrokedOnly); break; case ESplineCP: case EBezierCP: case ERadius: case EMinor: painter.newPath(); painter.moveTo(Vector(-4*z, -4*z)); painter.lineTo(Vector(4*z, -4*z)); painter.lineTo(Vector(4*z, 4*z)); painter.lineTo(Vector(-4*z, 4*z)); painter.closePath(); painter.drawPath(EFilledOnly); break; case EScissor: painter.newPath(); painter.moveTo(Vector(5*z, 0)); painter.lineTo(Vector(0, 5*z)); painter.lineTo(Vector(-5*z, 0)); painter.lineTo(Vector(0, -5*z)); painter.closePath(); painter.drawPath(EFilledOnly); break; } painter.popMatrix(); } } void ShapeTool::setShape(Shape shape, int which, double pen) { if (which == 1) iAuxShape = shape; else iShape = shape; iPen = pen; } void ShapeTool::clearMarks() { iMarks.clear(); } void ShapeTool::addMark(const Vector &v, TMarkType t) { SMark m; m.v = v; m.t = t; iMarks.push_back(m); } // -------------------------------------------------------------------- PasteTool::PasteTool(CanvasBase *canvas, lua_State *L0, int luatool, Object *obj) : LuaTool(canvas, L0, luatool) { iObject = obj; } PasteTool::~PasteTool() { delete iObject; } void PasteTool::draw(Painter &painter) const { painter.transform(iMatrix); painter.setStroke(Attribute(iColor)); iObject->drawSimple(painter); } // -------------------------------------------------------------------- ipe-7.1.4/src/ipe/controls_win.h0000644000175000017500000000643112120621776016417 0ustar otfriedotfried// -*- C++ -*- // -------------------------------------------------------------------- // Special widgets for Win32 // -------------------------------------------------------------------- /* This file is part of the extensible drawing editor Ipe. Copyright (C) 1993-2013 Otfried Cheong Ipe is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. As a special exception, you have permission to link Ipe with the CGAL library and distribute executables, as long as you follow the requirements of the Gnu General Public License in regard to all of the software in the executable aside from CGAL. Ipe 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 General Public License for more details. You should have received a copy of the GNU General Public License along with Ipe; if not, you can find it at "http://www.gnu.org/copyleft/gpl.html", or write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ #ifndef CONTROLS_WIN_H #define CONTROLS_WIN_H #include "ipelib.h" #define _WIN32_WINNT 0x0501 #define _WIN32_IE 0x0501 #include using namespace ipe; // -------------------------------------------------------------------- #if 0 class LayerBox : public QListWidget { Q_OBJECT public: LayerBox(QWidget *parent = 0); void set(const Page *page, int view); signals: void activated(String name, String layer); void showLayerBoxPopup(Vector v, String layer); public slots: void layerChanged(QListWidgetItem *item); protected: virtual void mouseReleaseEvent(QMouseEvent *e); virtual void mousePressEvent(QMouseEvent *e); void addAction(QMenu *m, QListWidgetItem *item, String name, const QString &text); private: bool iInSet; }; #endif // -------------------------------------------------------------------- class PathView { public: static void init(HINSTANCE hInstance); PathView(HWND parent, int id); HWND windowId() const { return hwnd; } void set(const AllAttributes &all, Cascade *sheet); inline POINT popupPos() const { return pos; } inline String action() const { return iAction; } private: static const char className[]; static LRESULT CALLBACK wndProc(HWND hwnd, UINT Message, WPARAM wParam, LPARAM lParam); void wndPaint(); void button(int x, int y); private: HWND hwnd; int idBase; POINT pos; Cascade *iCascade; AllAttributes iAll; String iAction; }; // -------------------------------------------------------------------- #if 0 class PageSorter : public QListWidget { Q_OBJECT public: PageSorter(Document *doc, int width, QWidget *parent = 0); int pageAt(int r) const; public slots: void deletePages(); void cutPages(); void insertPages(); private: virtual void contextMenuEvent(QContextMenuEvent *event); private: Document *iDoc; QList iCutList; int iActionRow; }; #endif extern void ipe_init_controls(HINSTANCE hInstance); // -------------------------------------------------------------------- #endif ipe-7.1.4/src/ipe/pathview_win.cpp0000644000175000017500000001454612120621776016744 0ustar otfriedotfried// -------------------------------------------------------------------- // Special widgets for Win32 // -------------------------------------------------------------------- /* This file is part of the extensible drawing editor Ipe. Copyright (C) 1993-2013 Otfried Cheong Ipe is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. As a special exception, you have permission to link Ipe with the CGAL library and distribute executables, as long as you follow the requirements of the Gnu General Public License in regard to all of the software in the executable aside from CGAL. Ipe 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 General Public License for more details. You should have received a copy of the GNU General Public License along with Ipe; if not, you can find it at "http://www.gnu.org/copyleft/gpl.html", or write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ #include "controls_win.h" #include "ipecairopainter.h" #include #include using namespace ipe; const char PathView::className[] = "ipePathViewClass"; // -------------------------------------------------------------------- PathView::PathView(HWND parent, int id) { iCascade = 0; idBase = id; HWND hwnd = CreateWindowEx(WS_EX_CLIENTEDGE, className, "", WS_CHILD | WS_VISIBLE, 0, 0, 0, 0, parent, NULL, (HINSTANCE) GetWindowLong(parent, GWL_HINSTANCE), this); if (hwnd == NULL) { MessageBox(NULL, "PathView creation failed!", "Error!", MB_ICONEXCLAMATION | MB_OK); exit(9); } assert(GetWindowLongPtr(hwnd, GWLP_USERDATA)); } void PathView::set(const AllAttributes &all, Cascade *sheet) { iCascade = sheet; iAll = all; InvalidateRect(hwnd, NULL, FALSE); } LRESULT CALLBACK PathView::wndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) { PathView *pv = (PathView *) GetWindowLongPtr(hwnd, GWLP_USERDATA); switch (message) { case WM_CREATE: { assert(pv == 0); LPCREATESTRUCT p = (LPCREATESTRUCT) lParam; pv = (PathView *) p->lpCreateParams; pv->hwnd = hwnd; SetWindowLongPtr(hwnd, GWLP_USERDATA, (LONG_PTR) pv); } break; case WM_PAINT: if (pv) pv->wndPaint(); return 0; case WM_LBUTTONDOWN: if (pv) pv->button(LOWORD(lParam), HIWORD(lParam)); break; case WM_RBUTTONUP: if (pv) { pv->pos.x = LOWORD(lParam); pv->pos.y = HIWORD(lParam); ClientToScreen(pv->hwnd, (LPPOINT) &pv->pos); SendMessage(GetParent(hwnd), WM_COMMAND, pv->idBase, (LPARAM) hwnd); } break; case WM_DESTROY: delete pv; break; default: break; } return DefWindowProc(hwnd, message, wParam, lParam); } void PathView::wndPaint() { InvalidateRect(hwnd, NULL, FALSE); RECT rc; GetClientRect(hwnd, &rc); int w = rc.right; int h = rc.bottom; PAINTSTRUCT ps; HDC hdc = BeginPaint(hwnd, &ps); cairo_surface_t *surface = cairo_win32_surface_create(hdc); cairo_t *cc = cairo_create(surface); cairo_set_source_rgb(cc, 1, 1, 0.8); cairo_rectangle(cc, 0, 0, w, h); cairo_fill(cc); if (iCascade) { cairo_translate(cc, 0, h); double zoom = 2.0; cairo_scale(cc, zoom, -zoom); Vector v0 = (1.0/zoom) * Vector(0.1 * w, 0.5 * h); Vector v1 = (1.0/zoom) * Vector(0.7 * w, 0.5 * h); Vector u1 = (1.0/zoom) * Vector(0.88 * w, 0.8 * h); Vector u2 = (1.0/zoom) * Vector(0.80 * w, 0.5 * h); Vector u3 = (1.0/zoom) * Vector(0.88 * w, 0.2 * h); Vector u4 = (1.0/zoom) * Vector(0.96 * w, 0.5 * h); CairoPainter painter(iCascade, 0, cc, 3.0, false); painter.setPen(iAll.iPen); painter.setDashStyle(iAll.iDashStyle); painter.setStroke(iAll.iStroke); painter.setFill(iAll.iFill); painter.pushMatrix(); painter.newPath(); painter.moveTo(v0); painter.lineTo(v1); painter.drawPath(EStrokedOnly); if (iAll.iFArrow) Path::drawArrow(painter, v1, Angle(0), iAll.iFArrowShape, iAll.iFArrowSize, 100.0); if (iAll.iRArrow) Path::drawArrow(painter, v0, Angle(IpePi), iAll.iRArrowShape, iAll.iRArrowSize, 100.0); painter.setDashStyle(Attribute::NORMAL()); painter.setTiling(iAll.iTiling); painter.newPath(); painter.moveTo(u1); painter.lineTo(u2); painter.lineTo(u3); painter.lineTo(u4); painter.closePath(); painter.drawPath(iAll.iPathMode); painter.popMatrix(); } cairo_surface_flush(surface); cairo_destroy(cc); cairo_surface_destroy(surface); EndPaint(hwnd, &ps); } void PathView::button(int x, int y) { RECT rc; GetClientRect(hwnd, &rc); int w = rc.right; if (x < w * 3 / 10) { iAction = iAll.iRArrow ? "rarrow|false" : "rarrow|true"; SendMessage(GetParent(hwnd), WM_COMMAND, idBase+1, (LPARAM) hwnd); } else if (x > w * 4 / 10 && x < w * 72 / 100) { iAction = iAll.iFArrow ? "farrow|false" : "farrow|true"; SendMessage(GetParent(hwnd), WM_COMMAND, idBase+1, (LPARAM) hwnd); } else if (x > w * 78 / 100) { switch (iAll.iPathMode) { case EStrokedOnly: iAction = "pathmode|strokedfilled"; break; case EStrokedAndFilled: iAction = "pathmode|filled"; break; case EFilledOnly: iAction = "pathmode|stroked"; break; } SendMessage(GetParent(hwnd), WM_COMMAND, idBase+1, (LPARAM) hwnd); } // show new status InvalidateRect(hwnd, NULL, FALSE); } void PathView::init(HINSTANCE hInstance) { WNDCLASSEX wc; wc.cbSize = sizeof(WNDCLASSEX); wc.style = 0; // CS_VREDRAW | CS_HREDRAW; wc.lpfnWndProc = wndProc; wc.cbClsExtra = 0; wc.cbWndExtra = 0; wc.hInstance = hInstance; wc.hCursor = LoadCursor(NULL, IDC_ARROW); wc.hbrBackground = (HBRUSH) GetStockObject(NULL_BRUSH); wc.lpszMenuName = NULL; // actually child id wc.lpszClassName = className; wc.hIcon = NULL; wc.hIconSm = NULL; if (!RegisterClassEx(&wc)) { MessageBox(NULL, "PathView control registration failed!", "Error!", MB_ICONEXCLAMATION | MB_OK); exit(9); } } // -------------------------------------------------------------------- ipe-7.1.4/src/ipe/lfs.cpp0000644000175000017500000004306012120621776015015 0ustar otfriedotfried/* This file is part of the extensible drawing editor Ipe. Copyright (C) 1993-2013 Otfried Cheong Ipe is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. As a special exception, you have permission to link Ipe with the CGAL library and distribute executables, as long as you follow the requirements of the Gnu General Public License in regard to all of the software in the executable aside from CGAL. Ipe 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 General Public License for more details. You should have received a copy of the GNU General Public License along with Ipe; if not, you can find it at "http://www.gnu.org/copyleft/gpl.html", or write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ /* ** LuaFileSystem ** Copyright Kepler Project 2003 (http://www.keplerproject.org/luafilesystem) ** ** File system manipulation library. ** This library offers these functions: ** lfs.attributes (filepath [, attributename]) ** lfs.chdir (path) ** lfs.currentdir () ** lfs.dir (path) ** lfs.lock (fh, mode) ** lfs.mkdir (path) ** lfs.rmdir (path) ** lfs.setmode (filepath, mode) ** lfs.symlinkattributes (filepath [, attributename]) -- thanks to Sam Roberts ** lfs.touch (filepath [, atime [, mtime]]) ** lfs.unlock (fh) ** ** $Id: lfs.c,v 1.53 2008/05/07 19:06:37 carregal Exp $ */ #define _LARGEFILE64_SOURCE #include #include #include #include #include #include #ifdef _WIN32 #include #include #include #include #include #else #include #include #include #include #include #endif extern "C" { #include "lua.h" #include "lauxlib.h" #include "lualib.h" } #ifdef NO_CHDIR #define chdir(p) (-1) #define chdir_error "Function 'chdir' not provided by system" #else #define chdir_error strerror(errno) #endif /* Define 'strerror' for systems that do not implement it */ #ifdef NO_STRERROR #define strerror(_) "System unable to describe the error" #endif /* Define 'getcwd' for systems that do not implement it */ #ifdef NO_GETCWD #define getcwd(p,s) NULL #define getcwd_error "Function 'getcwd' not provided by system" #else #define getcwd_error strerror(errno) #endif #define DIR_METATABLE "directory metatable" #define MAX_DIR_LENGTH 1023 typedef struct dir_data { int closed; #ifdef _WIN32 long hFile; char pattern[MAX_DIR_LENGTH+1]; #else DIR *dir; #endif } dir_data; #ifdef _WIN32 #define lfs_setmode(L,file,m) ((void)L, _setmode(_fileno(file), m)) #define STAT_STRUCT struct _stati64 #define STAT_FUNC _stati64 #else #define _O_TEXT 0 #define _O_BINARY 0 #define lfs_setmode(L,file,m) ((void)((void)file,m), \ luaL_error(L, LUA_QL("setmode") " not supported on this platform"), -1) #ifdef HAVE_STAT64 #define STAT_STRUCT struct stat64 #define STAT_FUNC stat64 #define LSTAT_FUNC lstat64 #else #define STAT_STRUCT struct stat #define STAT_FUNC stat #define LSTAT_FUNC lstat #endif #endif /* ** This function changes the working (current) directory */ static int change_dir (lua_State *L) { const char *path = luaL_checkstring(L, 1); if (chdir(path)) { lua_pushnil (L); lua_pushfstring (L,"Unable to change working directory to '%s'\n%s\n", path, chdir_error); return 2; } else { lua_pushboolean (L, 1); return 1; } } /* ** This function returns the current directory ** If unable to get the current directory, it returns nil ** and a string describing the error */ static int get_dir (lua_State *L) { char *path; if ((path = getcwd(NULL, 0)) == NULL) { lua_pushnil(L); lua_pushstring(L, getcwd_error); return 2; } else { lua_pushstring(L, path); free(path); return 1; } } /* ** Check if the given element on the stack is a file and returns it. */ static FILE *check_file (lua_State *L, int idx, const char *funcname) { FILE **fh = (FILE **)luaL_checkudata (L, idx, "FILE*"); if (fh == NULL) { luaL_error (L, "%s: not a file", funcname); return 0; } else if (*fh == NULL) { luaL_error (L, "%s: closed file", funcname); return 0; } else return *fh; } /* ** */ static int _file_lock (lua_State *L, FILE *fh, const char *mode, const long start, long len, const char *funcname) { int code; #ifdef _WIN32 /* lkmode valid values are: LK_LOCK Locks the specified bytes. If the bytes cannot be locked, the program immediately tries again after 1 second. If, after 10 attempts, the bytes cannot be locked, the constant returns an error. LK_NBLCK Locks the specified bytes. If the bytes cannot be locked, the constant returns an error. LK_NBRLCK Same as _LK_NBLCK. LK_RLCK Same as _LK_LOCK. LK_UNLCK Unlocks the specified bytes, which must have been previously locked. Regions should be locked only briefly and should be unlocked before closing a file or exiting the program. http://msdn.microsoft.com/library/default.asp?url=/library/en-us/vclib/html/_crt__locking.asp */ int lkmode; switch (*mode) { case 'r': lkmode = LK_NBLCK; break; case 'w': lkmode = LK_NBLCK; break; case 'u': lkmode = LK_UNLCK; break; default : return luaL_error (L, "%s: invalid mode", funcname); } if (!len) { fseek (fh, 0L, SEEK_END); len = ftell (fh); } fseek (fh, start, SEEK_SET); code = _locking (fileno(fh), lkmode, len); #else struct flock f; switch (*mode) { case 'w': f.l_type = F_WRLCK; break; case 'r': f.l_type = F_RDLCK; break; case 'u': f.l_type = F_UNLCK; break; default : return luaL_error (L, "%s: invalid mode", funcname); } f.l_whence = SEEK_SET; f.l_start = (off_t)start; f.l_len = (off_t)len; code = fcntl (fileno(fh), F_SETLK, &f); #endif return (code != -1); } #ifdef _WIN32 static int lfs_g_setmode (lua_State *L, FILE *f, int arg) { static const int mode[] = {_O_TEXT, _O_BINARY}; static const char *const modenames[] = {"text", "binary", NULL}; int op = luaL_checkoption(L, arg, NULL, modenames); int res = lfs_setmode(L, f, mode[op]); if (res != -1) { int i; lua_pushboolean(L, 1); for (i = 0; modenames[i] != NULL; i++) { if (mode[i] == res) { lua_pushstring(L, modenames[i]); goto exit; } } lua_pushnil(L); exit: return 2; } else { int en = errno; lua_pushnil(L); lua_pushfstring(L, "%s", strerror(en)); lua_pushinteger(L, en); return 3; } } #else static int lfs_g_setmode (lua_State *L, FILE *f, int arg) { lua_pushboolean(L, 0); lua_pushliteral(L, "setmode not supported on this platform"); return 2; } #endif static int lfs_f_setmode(lua_State *L) { return lfs_g_setmode(L, check_file(L, 1, "setmode"), 2); } /* ** Locks a file. ** @param #1 File handle. ** @param #2 String with lock mode ('w'rite, 'r'ead). ** @param #3 Number with start position (optional). ** @param #4 Number with length (optional). */ static int file_lock (lua_State *L) { FILE *fh = check_file (L, 1, "lock"); const char *mode = luaL_checkstring (L, 2); const long start = luaL_optlong (L, 3, 0); long len = luaL_optlong (L, 4, 0); if (_file_lock (L, fh, mode, start, len, "lock")) { lua_pushboolean (L, 1); return 1; } else { lua_pushnil (L); lua_pushfstring (L, "%s", strerror(errno)); return 2; } } /* ** Unlocks a file. ** @param #1 File handle. ** @param #2 Number with start position (optional). ** @param #3 Number with length (optional). */ static int file_unlock (lua_State *L) { FILE *fh = check_file (L, 1, "unlock"); const long start = luaL_optlong (L, 2, 0); long len = luaL_optlong (L, 3, 0); if (_file_lock (L, fh, "u", start, len, "unlock")) { lua_pushboolean (L, 1); return 1; } else { lua_pushnil (L); lua_pushfstring (L, "%s", strerror(errno)); return 2; } } static int make_dir (lua_State *L) { const char *path = luaL_checkstring (L, 1); int fail; #ifdef _WIN32 int oldmask = umask (0); fail = _mkdir (path); #else mode_t oldmask = umask( (mode_t)0 ); fail = mkdir (path, S_IRUSR | S_IWUSR | S_IXUSR | S_IRGRP | S_IWGRP | S_IXGRP | S_IROTH | S_IXOTH ); #endif if (fail) { lua_pushnil (L); lua_pushfstring (L, "%s", strerror(errno)); return 2; } umask (oldmask); lua_pushboolean (L, 1); return 1; } /* ** Removes a directory. ** @param #1 Directory path. */ static int remove_dir (lua_State *L) { const char *path = luaL_checkstring (L, 1); int fail; fail = rmdir (path); if (fail) { lua_pushnil (L); lua_pushfstring (L, "%s", strerror(errno)); return 2; } lua_pushboolean (L, 1); return 1; } /* ** Directory iterator */ static int dir_iter (lua_State *L) { #ifdef _WIN32 struct _finddata_t c_file; #else struct dirent *entry; #endif dir_data *d = (dir_data *)lua_touserdata (L, lua_upvalueindex (1)); luaL_argcheck (L, !d->closed, 1, "closed directory"); #ifdef _WIN32 if (d->hFile == 0L) { /* first entry */ if ((d->hFile = _findfirst (d->pattern, &c_file)) == -1L) { lua_pushnil (L); lua_pushstring (L, strerror (errno)); return 2; } else { lua_pushstring (L, c_file.name); return 1; } } else { /* next entry */ if (_findnext (d->hFile, &c_file) == -1L) { /* no more entries => close directory */ _findclose (d->hFile); d->closed = 1; return 0; } else { lua_pushstring (L, c_file.name); return 1; } } #else if ((entry = readdir (d->dir)) != NULL) { lua_pushstring (L, entry->d_name); return 1; } else { /* no more entries => close directory */ closedir (d->dir); d->closed = 1; return 0; } #endif } /* ** Closes directory iterators */ static int dir_close (lua_State *L) { dir_data *d = (dir_data *)lua_touserdata (L, 1); #ifdef _WIN32 if (!d->closed && d->hFile) { _findclose (d->hFile); d->closed = 1; } #else if (!d->closed && d->dir) { closedir (d->dir); d->closed = 1; } #endif return 0; } /* ** Factory of directory iterators */ static int dir_iter_factory (lua_State *L) { const char *path = luaL_checkstring (L, 1); dir_data *d = (dir_data *) lua_newuserdata (L, sizeof(dir_data)); d->closed = 0; #ifdef _WIN32 d->hFile = 0L; luaL_getmetatable (L, DIR_METATABLE); lua_setmetatable (L, -2); if (strlen(path) > MAX_DIR_LENGTH) luaL_error (L, "path too long: %s", path); else sprintf (d->pattern, "%s/*", path); #else luaL_getmetatable (L, DIR_METATABLE); lua_setmetatable (L, -2); d->dir = opendir (path); if (d->dir == NULL) luaL_error (L, "cannot open %s: %s", path, strerror (errno)); #endif lua_pushcclosure (L, dir_iter, 1); return 1; } /* ** Creates directory metatable. */ static int dir_create_meta (lua_State *L) { luaL_newmetatable (L, DIR_METATABLE); /* set its __gc field */ lua_pushstring (L, "__gc"); lua_pushcfunction (L, dir_close); lua_settable (L, -3); return 1; } #ifdef _WIN32 #ifndef S_ISDIR #define S_ISDIR(mode) (mode&_S_IFDIR) #endif #ifndef S_ISREG #define S_ISREG(mode) (mode&_S_IFREG) #endif #ifndef S_ISLNK #define S_ISLNK(mode) (0) #endif #ifndef S_ISSOCK #define S_ISSOCK(mode) (0) #endif #ifndef S_ISFIFO #define S_ISFIFO(mode) (0) #endif #ifndef S_ISCHR #define S_ISCHR(mode) (mode&_S_IFCHR) #endif #ifndef S_ISBLK #define S_ISBLK(mode) (0) #endif #endif /* ** Convert the inode protection mode to a string. */ #ifdef _WIN32 static const char *mode2string (unsigned short mode) { #else static const char *mode2string (mode_t mode) { #endif if ( S_ISREG(mode) ) return "file"; else if ( S_ISDIR(mode) ) return "directory"; else if ( S_ISLNK(mode) ) return "link"; else if ( S_ISSOCK(mode) ) return "socket"; else if ( S_ISFIFO(mode) ) return "named pipe"; else if ( S_ISCHR(mode) ) return "char device"; else if ( S_ISBLK(mode) ) return "block device"; else return "other"; } /* ** Set access time and modification values for file */ static int file_utime (lua_State *L) { const char *file = luaL_checkstring (L, 1); struct utimbuf utb, *buf; if (lua_gettop (L) == 1) /* set to current date/time */ buf = NULL; else { utb.actime = (time_t)luaL_optnumber (L, 2, 0); utb.modtime = (time_t)luaL_optnumber (L, 3, utb.actime); buf = &utb; } if (utime (file, buf)) { lua_pushnil (L); lua_pushfstring (L, "%s", strerror (errno)); return 2; } lua_pushboolean (L, 1); return 1; } /* inode protection mode */ static void push_st_mode (lua_State *L, STAT_STRUCT *info) { lua_pushstring (L, mode2string (info->st_mode)); } /* device inode resides on */ static void push_st_dev (lua_State *L, STAT_STRUCT *info) { lua_pushnumber (L, (lua_Number)info->st_dev); } /* inode's number */ static void push_st_ino (lua_State *L, STAT_STRUCT *info) { lua_pushnumber (L, (lua_Number)info->st_ino); } /* number of hard links to the file */ static void push_st_nlink (lua_State *L, STAT_STRUCT *info) { lua_pushnumber (L, (lua_Number)info->st_nlink); } /* user-id of owner */ static void push_st_uid (lua_State *L, STAT_STRUCT *info) { lua_pushnumber (L, (lua_Number)info->st_uid); } /* group-id of owner */ static void push_st_gid (lua_State *L, STAT_STRUCT *info) { lua_pushnumber (L, (lua_Number)info->st_gid); } /* device type, for special file inode */ static void push_st_rdev (lua_State *L, STAT_STRUCT *info) { lua_pushnumber (L, (lua_Number)info->st_rdev); } /* time of last access */ static void push_st_atime (lua_State *L, STAT_STRUCT *info) { lua_pushnumber (L, info->st_atime); } /* time of last data modification */ static void push_st_mtime (lua_State *L, STAT_STRUCT *info) { lua_pushnumber (L, info->st_mtime); } /* time of last file status change */ static void push_st_ctime (lua_State *L, STAT_STRUCT *info) { lua_pushnumber (L, info->st_ctime); } /* file size, in bytes */ static void push_st_size (lua_State *L, STAT_STRUCT *info) { lua_pushnumber (L, (lua_Number)info->st_size); } #ifndef _WIN32 /* blocks allocated for file */ static void push_st_blocks (lua_State *L, STAT_STRUCT *info) { lua_pushnumber (L, (lua_Number)info->st_blocks); } /* optimal file system I/O blocksize */ static void push_st_blksize (lua_State *L, STAT_STRUCT *info) { lua_pushnumber (L, (lua_Number)info->st_blksize); } #endif static void push_invalid (lua_State *L, STAT_STRUCT *info) { luaL_error(L, "invalid attribute name"); #ifndef _WIN32 info->st_blksize = 0; /* never reached */ #endif } typedef void (*_push_function) (lua_State *L, STAT_STRUCT *info); struct _stat_members { const char *name; _push_function push; }; struct _stat_members members[] = { { "mode", push_st_mode }, { "dev", push_st_dev }, { "ino", push_st_ino }, { "nlink", push_st_nlink }, { "uid", push_st_uid }, { "gid", push_st_gid }, { "rdev", push_st_rdev }, { "access", push_st_atime }, { "modification", push_st_mtime }, { "change", push_st_ctime }, { "size", push_st_size }, #ifndef _WIN32 { "blocks", push_st_blocks }, { "blksize", push_st_blksize }, #endif { NULL, push_invalid } }; /* ** Get file or symbolic link information */ static int _file_info_ (lua_State *L, int (*st)(const char*, STAT_STRUCT*)) { int i; STAT_STRUCT info; const char *file = luaL_checkstring (L, 1); if (st(file, &info)) { lua_pushnil (L); lua_pushfstring (L, "cannot obtain information from file `%s'", file); return 2; } if (lua_isstring (L, 2)) { int v; const char *member = lua_tostring (L, 2); if (strcmp (member, "mode") == 0) v = 0; #ifndef _WIN32 else if (strcmp (member, "blocks") == 0) v = 11; else if (strcmp (member, "blksize") == 0) v = 12; #endif else /* look for member */ for (v = 1; members[v].name; v++) if (*members[v].name == *member) break; /* push member value and return */ members[v].push (L, &info); return 1; } else if (!lua_istable (L, 2)) /* creates a table if none is given */ lua_newtable (L); /* stores all members in table on top of the stack */ for (i = 0; members[i].name; i++) { lua_pushstring (L, members[i].name); members[i].push (L, &info); lua_rawset (L, -3); } return 1; } /* ** Get file information using stat. */ static int file_info (lua_State *L) { return _file_info_ (L, STAT_FUNC); } /* ** Get symbolic link information using lstat. */ #ifndef _WIN32 static int link_info (lua_State *L) { return _file_info_ (L, LSTAT_FUNC); } #else static int link_info (lua_State *L) { lua_pushboolean(L, 0); lua_pushliteral(L, "symlinkattributes not supported on this platform"); return 2; } #endif /* ** Assumes the table is on top of the stack. */ static void set_info (lua_State *L) { lua_pushliteral (L, "_COPYRIGHT"); lua_pushliteral (L, "Copyright (C) 2003 Kepler Project"); lua_settable (L, -3); lua_pushliteral (L, "_DESCRIPTION"); lua_pushliteral (L, "LuaFileSystem is a Lua library developed to complement the set of functions related to file systems offered by the standard Lua distribution"); lua_settable (L, -3); lua_pushliteral (L, "_VERSION"); lua_pushliteral (L, "LuaFileSystem 1.4.1"); lua_settable (L, -3); } static const struct luaL_Reg fslib[] = { {"attributes", file_info}, {"chdir", change_dir}, {"currentdir", get_dir}, {"dir", dir_iter_factory}, {"lock", file_lock}, {"mkdir", make_dir}, {"rmdir", remove_dir}, {"symlinkattributes", link_info}, {"setmode", lfs_f_setmode}, {"touch", file_utime}, {"unlock", file_unlock}, {NULL, NULL}, }; extern int luaopen_lfs (lua_State *L) { dir_create_meta (L); luaL_newlib (L, fslib); lua_setglobal(L, "lfs"); set_info (L); return 1; } ipe-7.1.4/src/ipe/lua/0000755000175000017500000000000012120621776014303 5ustar otfriedotfriedipe-7.1.4/src/ipe/lua/mouse.lua0000644000175000017500000000426712120621776016147 0ustar otfriedotfried---------------------------------------------------------------------- -- Ipe mouse buttons ---------------------------------------------------------------------- --[[ This file is part of the extensible drawing editor Ipe. Copyright (C) 1993-2013 Otfried Cheong Ipe is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. As a special exception, you have permission to link Ipe with the CGAL library and distribute executables, as long as you follow the requirements of the Gnu General Public License in regard to all of the software in the executable aside from CGAL. Ipe 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 General Public License for more details. You should have received a copy of the GNU General Public License along with Ipe; if not, you can find it at "http://www.gnu.org/copyleft/gpl.html", or write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. --]] -- Available actions are: -- "select" -- "translate", "rotate", "stretch", -- "scale" (like "stretch" with Shift) -- "pan" -- "menu" (opens context menu) -- "shredder" (erases object closest to mouse) -- or write a Lua function with arguments (model, modifiers) -- left and left_shift cannot be remapped -- More than two modifiers are possible in the order -- shift_control_alt_meta -- e.g. left_shift_meta = "rotate" -- If your mouse has additional buttons, then you can also use -- button8, button9, and button10. -- (It seems other buttons are not passed through by Qt.) mouse = { left_alt = "translate", left_control = "select", left_shift_control = "select", middle = "pan", right = "menu", right_alt = "rotate", right_control = "stretch", right_shift_control = "scale", right_shift = "pan", button8 = "shredder", button10 = "translate", } ---------------------------------------------------------------------- ipe-7.1.4/src/ipe/lua/model.lua0000644000175000017500000005556712120621776016130 0ustar otfriedotfried---------------------------------------------------------------------- -- model.lua ---------------------------------------------------------------------- --[[ This file is part of the extensible drawing editor Ipe. Copyright (C) 1993-2013 Otfried Cheong Ipe is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. As a special exception, you have permission to link Ipe with the CGAL library and distribute executables, as long as you follow the requirements of the Gnu General Public License in regard to all of the software in the executable aside from CGAL. Ipe 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 General Public License for more details. You should have received a copy of the GNU General Public License along with Ipe; if not, you can find it at "http://www.gnu.org/copyleft/gpl.html", or write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. --]] MODEL = {} MODEL.__index = MODEL MODEL.snapmodes = { "snapvtx", "snapbd", "snapint", "snapgrid", "snapangle", "snapauto"} function MODEL:new(fname) local model = {} setmetatable(model, MODEL) model:init(fname) return model end function MODEL:init(fname) self.attributes = { pathmode = "stroked", stroke = "black", fill = "white", pen = "normal", dashstyle = "normal", farrowshape = "arrow/normal(spx)", rarrowshape = "arrow/normal(spx)", farrowsize = "normal", rarrowsize = "normal", farrow = false, rarrow = false, symbolsize = "normal", textsize = "normal", textstyle = "normal", transformabletext = prefs.transformable_text, horizontalalignment = "left", verticalalignment = "baseline", pinned = "none", transformations = "affine", linejoin = "normal", linecap = "normal", fillrule = "normal", markshape = "mark/disk(sx)", tiling = "normal", gradient = "normal", opacity = "opaque", } self.snap = { snapvtx = prefs.snap.vertex, snapbd = prefs.snap.boundary, snapint = prefs.snap.intersection, snapgrid = prefs.snap.grid, snapangle = prefs.snap.angle, snapauto = prefs.snap.autoangle, grid_visible = prefs.grid_visible, gridsize = prefs.grid_size, anglesize = prefs.angle_size, snap_distance = prefs.snap_distance, with_axes = false, origin = ipe.Vector(0,0), orientation = 0 } self.save_timestamp = 0 self.ui = AppUi(self) self.pristine = false self.first_show = true if fname then if ipe.fileExists(fname) then self:loadDocument(fname) else self:newDocument() self.file_name = fname self:setCaption() end end if not self.doc then self:newDocument() self.pristine = true end self.mode = "select" self.ui:setActionState("mode_select", true) self.ui:setActionState("grid_visible", self.snap.grid_visible) for i,e in ipairs(MODEL.snapmodes) do self.ui:setActionState(e, self.snap[e]) end self.ui:setSnap(self.snap) self.ui:setFifiVisible(true) self.auto_latex = prefs.auto_run_latex self.ui:setActionState("auto_latex", self.auto_latex) if self.auto_latex then self:runLatex() end if #self:getBookmarks() == 0 then self.ui:showTool("bookmarks", false) end if self:page():notes() == "" then self.ui:showTool("notes", false) end if prefs.autosave_interval then self.timer = ipeui.Timer(self, "autosave") self.timer:setInterval(1000 * prefs.autosave_interval) -- millisecs self.timer:start() end end function MODEL:sizeChanged() if self.first_show then self:action_fit_top() end self.first_show = false end ---------------------------------------------------------------------- function MODEL:resetGridSize() self.snap.gridsize = prefs.grid_size self.snap.anglesize = prefs.angle_size local gridsizes = allValues(self.doc:sheets(), "gridsize") if #gridsizes == 0 then gridsizes = { 16 } end if not indexOf(self.snap.gridsize, gridsizes) then self.snap.gridsize = gridsizes[1] end local anglesizes = allValues(self.doc:sheets(), "anglesize") if #anglesizes == 0 then anglesizes = { 45 } end if not indexOf(self.snap.anglesize, anglesizes) then self.snap.anglesize = anglesizes[1] end self.ui:setGridAngleSize(self.snap.gridsize, self.snap.anglesize) end function MODEL:print_attributes() print("----------------------------------------") for k in pairs(self.attributes) do print(k, self.attributes[k]) end print("----------------------------------------") end function MODEL:getString(msg, caption, start) if caption == nil then caption = "Ipe" end local d = ipeui.Dialog(self.ui:win(), caption) d:add("label", "label", {label=msg}, 1, 1) d:add("text", "input", {}, 2, 1) d:addButton("cancel", "Cancel", "reject") d:addButton("ok", "Ok", "accept") if start then d:set("text", start) end if d:execute() then return d:get("text") end end function MODEL:getDouble(caption, label, value, minv, maxv) local s = self:getString(label, caption, tostring(value)) -- print("getDouble", s) if s then local n = tonumber(s) if n and minv <= n and n <= maxv then return n end end end ---------------------------------------------------------------------- -- Return current page function MODEL:page() return self.doc[self.pno] end -- return table with selected objects on current page function MODEL:selection() local t = {} for i,obj,sel,layer in self:page():objects() do if sel then t[#t+1] = i end end return t end function MODEL:markAsUnmodified() self.save_timestamp = self.save_timestamp + 1 self.undo[#self.undo].save_timestamp = self.save_timestamp end -- is document modified? function MODEL:isModified() return (self.undo[#self.undo].save_timestamp ~= self.save_timestamp) end ---------------------------------------------------------------------- -- set window caption function MODEL:setCaption() local s = "Ipe " if config.toolkit == "qt" then s = s .. "[*]" elseif self:isModified() then s = s .. '*' end if self.file_name then s = s .. '"' .. self.file_name .. '" ' else s = s .. "[unsaved] " end --[[ if #self.doc > 1 then s = s .. string.format("Page %d/%d ", self.pno, #self.doc) end if self:page():countViews() > 1 then s = s .. string.format("(View %d/%d) ", self.vno, self:page():countViews()) end --]] self.ui:setWindowTitle(self:isModified(), s) end -- show a warning messageBox function MODEL:warning(text, details) ipeui.messageBox(self.ui:win(), "warning", text, details) end -- Set canvas to current page function MODEL:setPage() local p = self:page() self.ui:setPage(p, self.pno, self.vno, self.doc:sheets()) self.ui:setLayers(p, self.vno) self.ui:setNumbering(self.doc:properties().numberpages) self.ui:update() self:setCaption() self:setBookmarks() self.ui:setNotes(p:notes()) local vno if p:countViews() > 1 then vno = string.format("View %d/%d", self.vno, p:countViews()) end local pno if #self.doc > 1 then pno = string.format("Page %d/%d", self.pno, #self.doc) end self.ui:setNumbers(vno, p:markedView(self.vno), pno, p:marked()) end function MODEL:getBookmarks() local b = {} for _,p in self.doc:pages() do local t = p:titles() if t.section then if t.section ~= "" then b[#b+1] = t.section end elseif t.title ~= "" then b[#b+1] = t.title end if t.subsection then if t.subsection ~= "" then b[#b+1] = " " .. t.subsection end elseif t.title ~= "" then b[#b+1] = " " .. t.title end end return b end function MODEL:setBookmarks() self.ui:setBookmarks(self:getBookmarks()) end function MODEL:findPageForBookmark(index) local count = 0 for i,p in self.doc:pages() do local t = p:titles() if t.section then if t.section ~= "" then count = count + 1 end elseif t.title ~= "" then count = count + 1 end if t.subsection then if t.subsection ~= "" then count = count + 1 end elseif t.title ~= "" then count = count + 1 end if count >= index then return i end end end ---------------------------------------------------------------------- -- Deselect all objects not in current view, or in a locked layer. function MODEL:deselectNotInView() local p = self:page() for i,obj,sel,layer in p:objects() do if not p:visible(self.vno, i) or p:isLocked(layer) then p:setSelect(i, nil) end end p:ensurePrimarySelection() end -- Deselect all but primary selection function MODEL:deselectSecondary() local p = self:page() for i,obj,sel,layer in p:objects() do if sel ~= 1 then p:setSelect(i, nil) end end end -- If no selected object is close, select closest object. -- If there is a selected object close enough, returns true. -- Otherwise, check whether the closest object to the current mouse -- position is close enough. If so, unselect everything, make -- this object the primary selection, and return true. -- If not, return whether the page has a selection at all. -- If primaryOnly is true, the primary selection has to be close enough, -- otherwise it'll be replaced as above. function MODEL:updateCloseSelection(primaryOnly) local bound = prefs.close_distance local pos = self.ui:unsnappedPos() local p = self:page() -- is current selection close enough? if primaryOnly then local prim = p:primarySelection() if prim and p:distance(prim, pos, bound) < bound then return true end else for i,obj,sel,layer in p:objects() do if sel and p:distance(i, pos, bound) < bound then return true end end end -- current selection is not close enough: find closest object local closest for i,obj,sel,layer in p:objects() do if p:visible(self.vno, i) and not p:isLocked(layer) then local d = p:distance(i, pos, bound) if d < bound then closest = i; bound = d end end end if closest then -- deselect all, and select only closest object p:deselectAll() p:setSelect(closest, 1) return true else return p:hasSelection() end end ---------------------------------------------------------------------- -- Move to next/previous view function MODEL:nextView(delta) if 1 <= self.vno + delta and self.vno + delta <= self:page():countViews() then self.vno = self.vno + delta; self:deselectNotInView() elseif 1 <= self.pno + delta and self.pno + delta <= #self.doc then self.pno = self.pno + delta if delta > 0 then self.vno = 1; else self.vno = self:page():countViews() end end end -- Move to next/previous page function MODEL:nextPage(delta) if 1 <= self.pno + delta and self.pno + delta <= #self.doc then self.pno = self.pno + delta if delta > 0 then self.vno = 1; else self.vno = self:page():countViews() end end end -- change zoom and pan to fit box on screen function MODEL:fitBox(box) if box:isEmpty() then return end local cs = self.ui:canvasSize() local xfactor = 20.0 local yfactor = 20.0 if box:width() > 0 then xfactor = cs.x / box:width() end if box:height() > 0 then yfactor = cs.y / box:height() end local zoom = math.min(xfactor, yfactor) if zoom > prefs.max_zoom then zoom = prefs.max_zoom end if zoom < prefs.min_zoom then zoom = prefs.min_zoom end self.ui:setPan(0.5 * (box:bottomLeft() + box:topRight())) self.ui:setZoom(zoom) self.ui:update() end ---------------------------------------------------------------------- function MODEL:latexErrorBox(log) local d = ipeui.Dialog(self.ui:win(), "Ipe: error running Latex") d:add("label", "label", { label="An error occurred during the Pdflatex run. " .. "Please consult the logfile below." }, 1, 1) d:add("text", "text", { read_only=true, syntax="logfile" }, 2, 1) d:addButton("ok", "Ok", "accept") d:set("text", log) d:execute() end function MODEL:runLatex() local success, errmsg, result, log = self.doc:runLatex() if success then self.ui:setFontPool(self.doc) self.ui:update() return true elseif result == "latex" then self:latexErrorBox(log) return false else self:warning("An error occurred during the Pdflatex run", errmsg) end end function MODEL:autoRunLatex() if self.auto_latex then self:runLatex() end end -- checks if document is modified, and asks user if it can be discarded -- returns true if object is unmodified or user confirmed discarding function MODEL:checkModified() if self:isModified() then return ipeui.messageBox(self.ui:win(), "question", "The document has been modified", "Do you wish to discard the current document?", "discardcancel") == 0 else return true end end ---------------------------------------------------------------------- function MODEL:newDocument() self.pno = 1 self.vno = 1 self.file_name = nil self.undo = { {} } self.redo = {} self:markAsUnmodified() self.doc = ipe.Document() for _, w in ipairs(config.styleList) do local sheet = assert(ipe.Sheet(w)) self.doc:sheets():insert(1, sheet) end self:setPage() self.ui:setupSymbolicNames(self.doc:sheets()) self.ui:setAttributes(self.doc:sheets(), self.attributes) self:resetGridSize() self:action_normal_size() self.ui:setSnap(self.snap) self.ui:explain("New document") end function MODEL:loadDocument(fname) local doc, err = ipe.Document(fname) if doc then self.doc = doc self.file_name = fname self.pno = 1 self.vno = 1 self.undo = { {} } self.redo = {} self:markAsUnmodified() self:setPage() self.ui:setupSymbolicNames(self.doc:sheets()) self.ui:setAttributes(self.doc:sheets(), self.attributes) self:resetGridSize() self:action_normal_size() self.ui:setSnap(self.snap) self.ui:explain("Document '" .. fname .. "' loaded") local syms = self.doc:checkStyle() if #syms > 0 then self:warning("The document contains symbolic attributes " .. "that are not defined in the style sheet:", "
  • " .. table.concat(syms, "
  • ") .. "") end else self:warning("Document '" .. fname .. "' could not be opened", err) end end function MODEL:saveDocument(fname) if not fname then fname = self.file_name end local fm = formatFromFileName(fname) if not fm then self:warning("File not saved!", "You must save as *.xml, *.ipe, *.pdf, or *.eps") return end if fm == "eps" and self.doc:countTotalViews() > 1 then self:warning("File not saved!", "Only single-view documents can be saved in EPS format") return end -- run Latex if format is not XML if (fm ~= "xml" or prefs.auto_export_xml_to_eps or prefs.auto_export_xml_to_pdf) then if not self:runLatex() then self.ui:explain("Latex error - file not saved") return end end if fm == "eps" then local ok = true local msg = "The document uses the following features:
      " if self.doc:has("truetype") then ok = false msg = msg .. "
    • Truetype fonts" end if self.doc:has("gradients") then ok = false msg = msg .. "
    • Gradients" end if self.doc:has("transparency") then ok = false msg = msg .. "
    • Transparency" end if not ok then msg = msg .. "

    These cannot be saved in EPS format.

    " .. "

    You can save as PDF, and use pdftops to create a " .. "Postscript file.

    " self:warning("File not saved!", msg) return end end local props = self.doc:properties() props.modified = "D:" .. ipeui.currentDateTime() if props.created == "" then props.created = props.modified end props.creator = config.version self.doc:setProperties(props) if not self.doc:save(fname, fm) then self:warning("File not saved!", "Error saving the document") return end -- auto-exporting if fm == "xml" and prefs.auto_export_xml_to_eps then self:auto_export("eps", fname) end if fm == "xml" and prefs.auto_export_xml_to_pdf then self:auto_export("pdf", fname) end if fm == "eps" and prefs.auto_export_eps_to_pdf then self:auto_export("pdf", fname) end if fm == "pdf" and prefs.auto_export_pdf_to_eps then self:auto_export("eps", fname) end self:markAsUnmodified() self.ui:explain("Saved document '" .. fname .. "'") self.file_name = fname self:setCaption() return true end function MODEL:auto_export(fm, fname) local ename = fname:sub(1,-4) .. fm if prefs.auto_export_only_if_exists and not ipe.fileExists(ename) then return end local result if fm == "eps" then result = self.doc:exportView(ename, fm, nil, 1, 1) else result = self.doc:save(ename, fm, { export=true } ) end if not result then self:warning("Auto-exporting failed", "I could not export in format '" .. fm .. "' to file '" .. ename .. "'.") end end ---------------------------------------------------------------------- function MODEL:autosave() -- only autosave if document has been modified if not self:isModified() then return end local f if prefs.autosave_filename:find("%%s") then if self.file_name then f = self.file_name:match("/([^/]+)$") or self.file_name else f = "unnamed" end f = string.format(prefs.autosave_filename, f) else f = prefs.autosave_filename end self.ui:explain("Autosaving to " .. f .. "...") if not self.doc:save(f, "xml") then ipeui.messageBox(self.ui:win(), "critical", "Autosaving failed!") end end ---------------------------------------------------------------------- function MODEL:closeEvent() if self == first_model then first_model = nil end if self:isModified() then local r = ipeui.messageBox(self.ui:win(), "question", "The document has been modified", "Do you wish to save the document?", "savediscardcancel") if r == 1 then return self:action_save() else return r == 0 end else return true end end ---------------------------------------------------------------------- -- TODO: limit on undo stack size? function MODEL:registerOnly(t) self.pristine = false -- store it on undo stack self.undo[#self.undo + 1] = t -- flush redo stack self.redo = {} self:setPage() end function MODEL:register(t) -- store selection t.original_selection = self:selection() t.original_primary = self:page():primarySelection() -- perform action t.redo(t, self.doc) self:registerOnly(t) self.ui:explain(t.label) if t.style_sheets_changed then self.ui:setupSymbolicNames(self.doc:sheets()) self.ui:setAttributes(self.doc:sheets(), self.attributes) end end function MODEL:creation(label, obj) local t = { label=label, pno=self.pno, vno=self.vno, layer=self:page():active(self.vno), object=obj } t.undo = function (t, doc) doc[t.pno]:remove(#doc[t.pno]) end t.redo = function (t, doc) doc[t.pno]:deselectAll() doc[t.pno]:insert(nil, t.object, 1, t.layer) end self:register(t) end function MODEL:transformation(mode, m) local t = { label = mode, pno = self.pno, vno = self.vno, selection = self:selection(), original = self:page():clone(), matrix = m, undo = revertOriginal, } t.redo = function (t, doc) local p = doc[t.pno] for _,i in ipairs(t.selection) do p:transform(i, t.matrix) end end self:register(t) end function MODEL:setAttribute(prop, value) local t = { label="set attribute " .. prop .. " to " .. tostring(value), pno=self.pno, vno=self.vno, selection=self:selection(), original=self:page():clone(), property=prop, value=value, undo=revertOriginal, stroke=self.attributes.stroke, fill=self.attributes.fill, } t.redo = function (t, doc) local p = doc[t.pno] local changed = false for _,i in ipairs(t.selection) do if p:setAttribute(i, t.property, t.value, t.stroke, t.fill) then changed = true end end return changed end if (t.redo(t, self.doc)) then t.original_selection = t.selection t.original_primary = self:page():primarySelection() self:registerOnly(t) end end ---------------------------------------------------------------------- HELPER = {} HELPER.__index = HELPER function HELPER.new(model) local helper = {} setmetatable(helper, HELPER) helper.model = model return helper end function HELPER:message(m) self.model.ui:explain(m) end function HELPER:messageBox(text, details, buttons) return ipeui.messageBox(self.model.ui:win(), nil, text, details, buttons) end function HELPER:getString(m) return self.model:getString(m) end function MODEL:runIpelet(label, ipelet, num) local helper = HELPER.new(self) local t = { label="ipelet '" .. label .."'", pno=self.pno, vno=self.vno, original=self:page():clone(), undo=revertOriginal, redo=revertFinal, original_selection = self:selection(), original_primary = self:page():primarySelection(), } local need_undo = ipelet:run(num or 1, self:page(), self.doc, self.pno, self.vno, self:page():active(self.vno), self.attributes, helper) if need_undo then t.final = self:page():clone() self:registerOnly(t) end self:setPage() end ---------------------------------------------------------------------- function MODEL:action_undo() if #self.undo <= 1 then self.ui:explain("No more undo information available") return end t = self.undo[#self.undo] table.remove(self.undo) t.undo(t, self.doc) self.ui:explain("Undo '" .. t.label .. "'") self.redo[#self.redo + 1] = t if t.pno then self.pno = t.pno elseif t.pno0 then self.pno = t.pno0 end if t.vno then self.vno = t.vno elseif t.vno0 then self.vno = t.vno0 end local p = self:page() p:deselectAll() if t.original_selection then for _, no in ipairs(t.original_selection) do p:setSelect(no, 2) end end if t.original_primary then p:setSelect(t.original_primary, 1) end self:setPage() if t.style_sheets_changed then self.ui:setupSymbolicNames(self.doc:sheets()) self.ui:setAttributes(self.doc:sheets(), self.attributes) end end function MODEL:action_redo() if #self.redo == 0 then self.ui:explain("No more redo information available") return end t = self.redo[#self.redo] table.remove(self.redo) t.redo(t, self.doc) self.ui:explain("Redo '" .. t.label .. "'") self.undo[#self.undo + 1] = t if t.pno then self.pno = t.pno elseif t.pno1 then self.pno = t.pno1 end if t.vno then self.vno = t.vno elseif t.vno1 then self.vno = t.vno1 end self:page():deselectAll() self:setPage() if t.style_sheets_changed then self.ui:setupSymbolicNames(self.doc:sheets()) self.ui:setAttributes(self.doc:sheets(), self.attributes) end end ---------------------------------------------------------------------- ipe-7.1.4/src/ipe/lua/editpath.lua0000644000175000017500000007215312120621776016620 0ustar otfriedotfried---------------------------------------------------------------------- -- editpath.lua ---------------------------------------------------------------------- --[[ This file is part of the extensible drawing editor Ipe. Copyright (C) 1993-2013 Otfried Cheong Ipe is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. As a special exception, you have permission to link Ipe with the CGAL library and distribute executables, as long as you follow the requirements of the Gnu General Public License in regard to all of the software in the executable aside from CGAL. Ipe 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 General Public License for more details. You should have received a copy of the GNU General Public License along with Ipe; if not, you can find it at "http://www.gnu.org/copyleft/gpl.html", or write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. --]] EDITTOOL = {} EDITTOOL.__index = EDITTOOL local VERTEX = 1 local SPLINECP = 2 local BEZIERCP = 3 local CENTER = 4 local RADIUS = 5 local MINOR = 6 local CURRENT = 7 local SCISSOR = 8 ---------------------------------------------------------------------- function revertSubpath(t, shape) shape[t.spNum] = t.original end -- clone a subpath -- reuses the same CP (Vector) objects function cloneSubpath(sp) local nsp = {} for n in pairs(sp) do local t = sp[n] if type(t) == "table" then local nt = {} for nn in pairs(t) do nt[nn] = t[nn] end t = nt end nsp[n] = t end return nsp end local function recomputeMatrix(seg, cpno) local alpha, beta = seg.arc:angles() local p = ipe.Direction(alpha) local q = ipe.Direction(beta) local cl if cpno == 1 then cl = ipe.LineThrough(V(0,0), q) p = seg.arc:matrix():inverse() * seg[cpno] else -- cpno == 2 cl = ipe.LineThrough(V(0,0), p) q = seg.arc:matrix():inverse() * seg[cpno] end local center = ipe.Bisector(p, q):intersects(cl) if center and center:sqLen() < 1e10 then local radius = (p - center):len() alpha = (p - center):angle() beta = (q - center):angle() local m = (seg.arc:matrix() * ipe.Matrix(radius, 0, 0, radius, center.x, center.y)) seg.arc = ipe.Arc(m, alpha, beta) end end function moveCP(shape, spno, segno, cpno, v) local sp = shape[spno] if sp.type == "closedspline" then sp[cpno] = v elseif sp.type == "ellipse" then if cpno == 0 then -- center local m = sp[1]:elements() m[5] = v.x m[6] = v.y sp[1] = ipe.Matrix(m) elseif cpno == 1 then -- radius local u = sp[1]:inverse() * v local radius = u:len() local alpha = u:angle() local m = (sp[1] * ipe.Matrix(radius, 0, 0, radius, 0, 0) * ipe.Rotation(alpha)) if not m:isSingular() then sp[1] = m end elseif cpno == 2 then -- minor local u = sp[1]:inverse() * v local m = sp[1] * ipe.Matrix(1, 0, u.x, u.y, 0, 0) if not m:isSingular() then sp[1] = m end end else -- curve local seg = sp[segno] if cpno == 0 then -- center of arc local v1 = seg.arc:matrix():inverse() * v local alpha, beta = seg.arc:angles() local p, q = ipe.Direction(alpha), ipe.Direction(beta) local l = ipe.Bisector(p, q) local center = l:project(v1) local radius = (p - center):len() local m = ipe.Matrix(radius, 0, 0, radius, center.x, center.y) m = seg.arc:matrix() * m seg.arc = ipe.Arc(m, (p - center):angle(), (q - center):angle()) else seg[cpno] = v if cpno == 1 and segno > 1 then local pseg = sp[segno - 1] pseg[#pseg] = v elseif cpno == #seg and segno < #sp then sp[segno + 1][1] = v end if seg.type == "arc" then recomputeMatrix(seg, cpno) end if segno > 1 and cpno == 1 and sp[segno - 1].type == "arc" then recomputeMatrix(sp[segno - 1], 2) end if segno < #sp and cpno == #seg and sp[segno + 1].type == "arc" then recomputeMatrix(sp[segno + 1], 1) end end end end ---------------------------------------------------------------------- function EDITTOOL:new(model, prim, obj) local tool = {} setmetatable(tool, EDITTOOL) tool.model = model tool.undo = {} tool.primary = prim tool.obj = obj tool.shape = obj:shape() transformShape(obj:matrix(), tool.shape) model.ui:shapeTool(tool) tool.setColor(1.0, 0, 0) tool:resetCP() tool:setShapeMarks() return tool end ---------------------------------------------------------------------- function EDITTOOL:resetCP() self.spNum = 1 self.segNum = 1 self.cpNum = 1 if self.shape[1].type == "ellipse" then self.cpNum = 0 end end function EDITTOOL:type() local cur = self.shape[self.spNum] if cur.type == "closedspline" then return SPLINECP end if self.cpNum == 0 then return CENTER end if cur.type == "ellipse" then if self.cpNum == 1 then return RADIUS else return MINOR end end cur = cur[self.segNum] if self.cpNum == 1 or self.cpNum == #cur then return VERTEX end if cur.type == "spline" then return SPLINECP end if cur.type == "bezier" or cur.type == "quad" then return BEZIERCP end -- must be center of arc return CENTER end function EDITTOOL:current() local cur = self.shape[self.spNum] if cur.type == "ellipse" then if self.cpNum == 0 then return cur[1]:translation() elseif self.cpNum == 1 then return cur[1] * V(1,0) elseif self.cpNum == 2 then return cur[1] * V(0,1) end end if cur.type == "curve" then cur = cur[self.segNum] end if self.cpNum == 0 then cur = cur.arc:matrix():translation() else cur = cur[self.cpNum] end return cur end function EDITTOOL:canDelete() local t = self:type() if t == SPLINECP then return true end if t == VERTEX then local sp = self.shape[self.spNum] if sp[self.segNum].type ~= "segment" then return false end if self.cpNum == 1 then return self.segNum == 1 or sp[self.segNum - 1].type == "segment" end if self.cpNum == 2 then return self.segNum == #sp or sp[self.segNum + 1].type == "segment" end end return false end ---------------------------------------------------------------------- function EDITTOOL:setShapeMarks() local m = {} local aux = {} for _, sp in ipairs(self.shape) do if sp.type == "closedspline" then for _,cp in ipairs(sp) do m[#m + 1] = cp m[#m + 1] = SPLINECP end local as = { type="curve", closed=true } for i = 2,#sp do as[#as + 1] = { type="segment", sp[i-1], sp[i] } end aux[#aux + 1] = as elseif sp.type == "curve" then m[#m + 1] = sp[1][1] m[#m + 1] = VERTEX for _,seg in ipairs(sp) do m[#m + 1] = seg[#seg] m[#m + 1] = VERTEX if seg.type=="quad" or seg.type=="bezier" or seg.type=="spline" then for i = 2,#seg-1 do m[#m + 1] = seg[i] m[#m + 1] = seg.type=="spline" and SPLINECP or BEZIERCP end local as = { type="curve", closed=false } for i = 2,#seg do as[#as + 1] = { type="segment", seg[i-1], seg[i] } end aux[#aux + 1] = as elseif seg.type == "arc" then m[#m + 1] = seg.arc:matrix():translation() m[#m + 1] = CENTER end end else -- ellipse m[#m + 1] = sp[1]:translation() m[#m + 1] = CENTER m[#m + 1] = sp[1] * V(1, 0) m[#m + 1] = RADIUS m[#m + 1] = sp[1] * V(0, 1) m[#m + 1] = MINOR end end m[#m + 1] = self:current() m[#m + 1] = CURRENT if self.scissor then m[#m + 1] = self.scissorPos m[#m + 1] = SCISSOR end self.setShape(self.shape) self.setShape(aux, 1) self.setMarks(m) end function EDITTOOL:find(v) local bd = 1000000 -- maybe init with current vertex local spnum, segnum, cpnum for i,sp in ipairs(self.shape) do if sp.type == "closedspline" then for j,cp in ipairs(sp) do if (v-cp):sqLen() < bd then bd = (v-cp):sqLen() spnum = i segnum = 1 cpnum = j end end elseif sp.type == "ellipse" then local cp = sp[1]:translation() if (v-cp):sqLen() < bd then bd = (v-cp):sqLen() spnum = i segnum = 1 cpnum = 0 end cp = sp[1] * V(1,0) if (v-cp):sqLen() < bd then bd = (v-cp):sqLen() spnum = i segnum = 1 cpnum = 1 end cp = sp[1] * V(0,1) if (v-cp):sqLen() < bd then bd = (v-cp):sqLen() spnum = i segnum = 1 cpnum = 2 end else -- curve for j,seg in ipairs(sp) do for k,cp in ipairs(seg) do if (v-cp):sqLen() < bd then bd = (v-cp):sqLen() spnum = i segnum = j cpnum = k end end if seg.type == "arc" then local cp = seg.arc:matrix():translation() if (v-cp):sqLen() < bd then bd = (v-cp):sqLen() spnum = i segnum = j cpnum = 0 end end end end end return spnum, segnum, cpnum end ---------------------------------------------------------------------- function EDITTOOL:action_delete_subpath() local t = { label = "delete subpath", spNum = self.spNum, original = table.remove(self.shape, self.spNum), undo = function (t, shape) table.insert(shape, t.spNum, t.original) end } self.undo[#self.undo + 1] = t self:resetCP() end function EDITTOOL:action_delete() local sp = self.shape[self.spNum] local t = { label = "delete control point", spNum = self.spNum, original = cloneSubpath(sp), undo = revertSubpath } if sp.type == "closedspline" then -- cannot have closed spline with less than 3 cp if #sp < 4 then return end table.remove(sp, self.cpNum) elseif sp.type == "curve" then local seg = sp[self.segNum] if 1 < self.cpNum and self.cpNum < #seg then -- must be SPLINECP table.remove(seg, self.cpNum) if #seg == 2 then seg.type = "segment" end else -- VERTEX assert(seg.type == "segment") -- cannot delete from last segment or from last triangle if #sp == 1 or sp.closed and #sp == 2 then return end if self.cpNum == 1 and self.segNum == 1 then table.remove(sp, 1) elseif self.cpNum == 2 and self.segNum == #sp then table.remove(sp, #sp) else -- not first vertex, not last vertex if self.cpNum == 1 then self.segNum = self.segNum - 1 seg = sp[self.segNum] assert(seg.type == "segment") self.cpNum = 2 end assert(self.cpNum == 2) sp[self.segNum + 1][1] = seg[1] table.remove(sp, self.segNum) end end end self.undo[#self.undo + 1] = t self:resetCP() end function EDITTOOL:action_duplicate() local sp = self.shape[self.spNum] local t = { label = "duplicate control point", spNum = self.spNum, original = cloneSubpath(sp), undo = revertSubpath } if sp.type == "closedspline" then local cp = sp[self.cpNum] table.insert(sp, self.cpNum, cp) local pcp, ncp if self.cpNum > 1 then pcp = sp[self.cpNum - 1] else pcp = sp[#sp] end if self.cpNum < #sp-1 then ncp = sp[self.cpNum + 2] else ncp = sp[1] end sp[self.cpNum] = 0.9 * cp + 0.1 * pcp sp[self.cpNum + 1] = 0.9 * cp + 0.1 * ncp else assert(sp.type == "curve") local seg = sp[self.segNum] local cp = seg[self.cpNum] if 1 < self.cpNum and self.cpNum < #seg then assert(seg.type == "spline") table.insert(seg, self.cpNum, cp) local pcp = seg[self.cpNum - 1] local ncp = seg[self.cpNum + 2] seg[self.cpNum] = 0.9 * cp + 0.1 * pcp seg[self.cpNum + 1] = 0.9 * cp + 0.1 * ncp else if self.cpNum == #sp[self.segNum] then self.segNum = self.segNum + 1 self.cpNum = 1 end assert(self.cpNum == 1) local seg = { type="segment", cp, cp } table.insert(sp, self.segNum, seg) if self.segNum > 1 then local pseg = sp[self.segNum - 1] seg[1] = 0.9 * cp + 0.1 * pseg[#pseg - 1] pseg[#pseg] = seg[1] end if self.segNum < #sp then local nseg = sp[self.segNum + 1] seg[2] = 0.9 * cp + 0.1 * nseg[2] nseg[1] = seg[2] end end end self.undo[#self.undo + 1] = t end function EDITTOOL:action_cut() local sp = self.shape[self.spNum] local t = { label = "cut at vertex", spNum = self.spNum, original = cloneSubpath(sp), undo = function (t, shape) shape[t.spNum] = t.original if t.newSpNum then table.remove(shape, t.newSpNum) end end } assert(sp.type == "curve") if not sp.closed then -- cannot cut at first or last vertex if self.segNum == 1 and self.cpNum == 1 then return end if self.segNum == #sp and self.cpNum ~= 1 then return end if self.cpNum ~= 1 then self.segNum = self.segNum + 1 self.cpNum = 1 end local nsp = { type = "curve", closed = false } for i = self.segNum,#sp do nsp[#nsp + 1] = sp[i] end for i = #sp,self.segNum,-1 do table.remove(sp, i) end self.spNum = self.spNum + 1 t.newSpNum = self.spNum table.insert(self.shape, t.newSpNum, nsp) self.segNum = 1 else -- sp is closed sp.closed = false local lastseg = sp[#sp] local newseg = { type = "segment", lastseg[#lastseg], sp[1][1] } if self.segNum == 1 and self.cpNum == 1 then sp[#sp + 1] = newseg elseif self.segNum == #sp and self.cpNum ~= 1 then table.insert(sp, 1, newseg) else -- cutting somewhere else if self.cpNum ~= 1 then self.segNum = self.segNum + 1 self.cpNum = 1 end sp[#sp + 1] = newseg -- move self.segNum - 1 segments from front to back for i=1,self.segNum - 1 do local seg = table.remove(sp, 1) sp[#sp + 1] = seg end end self.segNum = 1 self.cpNum = 1 end end function EDITTOOL:action_convert_spline() local sp = self.shape[self.spNum] local t = { label = "convert spline to Beziers", spNum = self.spNum, original = cloneSubpath(sp), undo = revertSubpath } if sp.type == "closedspline" then local beziers = ipe.splineToBeziers(sp, true) beziers.type = "curve" beziers.closed = false self.shape[self.spNum] = beziers else local beziers = ipe.splineToBeziers(sp[self.segNum], false) table.remove(sp, self.segNum) for i=1,#beziers do table.insert(sp, self.segNum + i - 1, beziers[i]) end end self.undo[#self.undo + 1] = t end ---------------------------------------------------------------------- -- subdivide at parameter t (0 <= t <= 1) local function subdivideBezier(bez, t) local tt = 1 - t local l = {} local r = {} l[1] = bez[1]; l[2] = tt * bez[1] + t * bez[2] local h = tt * bez[2] + t * bez[3] l[3] = tt * l[2] + t * h r[3] = tt * bez[3] + t * bez[4] r[2] = tt * h + t * r[3] r[1] = tt * l[3] + t * r[2] l[4] = r[1] r[4] = bez[4] return l, r end -- subdivide at parameter t (0 <= t <= 1) local function subdivideQuad(bez, t) local tt = 1 - t local l = {} local r = {} l[1] = bez[1]; l[2] = tt * bez[1] + t * bez[2] r[2] = tt * bez[2] + t * bez[3] r[1] = tt * l[2] + t * r[2] l[3] = r[1] r[3] = bez[3] return l, r end function EDITTOOL:cutter_ellipse() local sp = self.shape[self.spNum] local t = { label = "cut ellipse", spNum = self.spNum, original = cloneSubpath(sp), undo = revertSubpath, } local alpha, _ = self.scissor(self.model.ui:pos()) sp.type = "curve" sp.closed = false local arc = ipe.Arc(sp[1], alpha, alpha - 0.2) local cp1, cp2 = arc:endpoints() sp[1] = { type = "arc", arc = arc, cp1, cp2 } self.undo[#self.undo + 1] = t end function EDITTOOL:cutter_arc() local sp = self.shape[self.spNum] local t = { label = "cut arc", spNum = self.spNum, original = cloneSubpath(sp), undo = function (t, shape) shape[t.spNum] = t.original if t.newSpNum then table.remove(shape, t.newSpNum) end end } local nalpha, _ = self.scissor(self.model.ui:pos()) local seg = sp[self.segNum] local alpha, beta = seg.arc:angles() local narc1 = ipe.Arc(seg.arc:matrix(), alpha, nalpha) local narc2 = ipe.Arc(seg.arc:matrix(), nalpha, beta) local npos, _ = narc2:endpoints() local nseg1 = { type = "arc", arc = narc1, seg[1], npos } local nseg2 = { type = "arc", arc = narc2, npos, seg[2] } if not sp.closed then local nsp = { type = "curve", closed = false, nseg2 } for i = self.segNum+1,#sp do nsp[#nsp + 1] = sp[i] end for i = #sp,self.segNum+1,-1 do table.remove(sp, i) end sp[self.segNum] = nseg1 t.newSpNum = self.spNum + 1 table.insert(self.shape, t.newSpNum, nsp) else -- sp is closed sp.closed = false local lastseg = sp[#sp] local nsp = { type = "curve", closed = false, nseg2 } for i = self.segNum+1,#sp do nsp[#nsp + 1] = sp[i] end nsp[#nsp + 1] = { type = "segment", lastseg[#lastseg], sp[1][1] } for i = 1,self.segNum-1 do nsp[#nsp + 1] = sp[i] end nsp[#nsp + 1] = nseg1 self.shape[self.spNum] = nsp self.segNum = #nsp end self.undo[#self.undo + 1] = t end function EDITTOOL:cutter_bezier() local sp = self.shape[self.spNum] local t = { label = "cut bezier", spNum = self.spNum, original = cloneSubpath(sp), undo = function (t, shape) shape[t.spNum] = t.original if t.newSpNum then table.remove(shape, t.newSpNum) end end } local param, _ = self.scissor(self.model.ui:pos()) local seg = sp[self.segNum] local nseg1, nseg2 if seg.type == "bezier" then nseg1, nseg2 = subdivideBezier(seg, param) nseg1.type = "bezier" nseg2.type = "bezier" else nseg1, nseg2 = subdivideQuad(seg, param) nseg1.type = "quad" nseg2.type = "quad" end if not sp.closed then local nsp = { type = "curve", closed = false, nseg2 } for i = self.segNum+1,#sp do nsp[#nsp + 1] = sp[i] end for i = #sp,self.segNum+1,-1 do table.remove(sp, i) end sp[self.segNum] = nseg1 t.newSpNum = self.spNum + 1 table.insert(self.shape, t.newSpNum, nsp) else -- sp is closed sp.closed = false local lastseg = sp[#sp] local nsp = { type = "curve", closed = false, nseg2 } for i = self.segNum+1,#sp do nsp[#nsp + 1] = sp[i] end nsp[#nsp + 1] = { type = "segment", lastseg[#lastseg], sp[1][1] } for i = 1,self.segNum-1 do nsp[#nsp + 1] = sp[i] end nsp[#nsp + 1] = nseg1 self.shape[self.spNum] = nsp self.segNum = #nsp end self.undo[#self.undo + 1] = t end ---------------------------------------------------------------------- local function scissor_arc(pos, arc) local t, p = arc:snap(pos) return t, p end local function scissor_bezier(pos, bezier) local t, p = bezier:snap(pos) return t, p end function EDITTOOL:action_cut_bezier() local sp = self.shape[self.spNum] local seg = sp[self.segNum] local bezier if seg.type == "bezier" then bezier = ipe.Bezier(seg[1], seg[2], seg[3], seg[4]) else bezier = ipe.Quad(seg[1], seg[2], seg[3]) end self.scissor = function (pos) return scissor_bezier(pos, bezier) end self.scissorPos = sp[self.segNum][1] self.cutter = "cutter_bezier" end function EDITTOOL:action_cut_arc() local sp = self.shape[self.spNum] local arc = sp[self.segNum].arc self.scissor = function (pos) return scissor_arc(pos, arc) end self.scissorPos = sp[self.segNum][1] self.cutter = "cutter_arc" end function EDITTOOL:action_cut_ellipse() local sp = self.shape[self.spNum] local arc = ipe.Arc(sp[1]) self.scissor = function (pos) return scissor_arc(pos, arc) end self.scissorPos = arc:matrix() * V(1,0) self.cutter = "cutter_ellipse" end ---------------------------------------------------------------------- function EDITTOOL:action_undo() if #self.undo == 0 then self.model:warning("Nothing to undo") return end local t = self.undo[#self.undo] table.remove(self.undo) t.undo(t, self.shape) self:resetCP() self.model.ui:explain("Undo " .. t.label) end ---------------------------------------------------------------------- function EDITTOOL:showMenu() local t = self:type() local m = ipeui.Menu(self.model.ui:win()) local gp = self.model.ui:globalPos() if self:canDelete() then m:add("action_delete", "Delete vertex") end if t == VERTEX or t == SPLINECP then m:add("action_duplicate", "Duplicate vertex") end if t == VERTEX then m:add("action_cut", "Cut at vertex") end if #self.shape > 1 then m:add("action_delete_subpath", "Delete subpath") end if t == SPLINECP then m:add("action_convert_spline", "Convert spline to Beziers") end if t == BEZIERCP then m:add("action_cut_bezier", "Cut Bezier spline") end if t == CENTER then if self.shape[self.spNum].type == "ellipse" then m:add("action_cut_ellipse", "Cut ellipse") else m:add("action_cut_arc", "Cut arc") end end m:add("action_undo", "Undo") local item = m:execute(gp.x, gp.y) if item then self[item](self) self:setShapeMarks() self.model.ui:update(false) -- update tool end end ---------------------------------------------------------------------- function EDITTOOL:mouseButton(button, modifiers, press) self.moving = false if self.scissor and press and button == 1 then self[self.cutter](self) self.scissor = nil self:setShapeMarks() self.model.ui:update(false) -- update tool self:explain() return end self.scissor = nil if not press then if button == 2 then self.spNum, self.segNum, self.cpNum = self:find(self.model.ui:unsnappedPos()) self:showMenu() return end else -- press if button == 1 then self.spNum, self.segNum, self.cpNum = self:find(self.model.ui:unsnappedPos()) self.moving = true local t = { label = "move", original = cloneSubpath(self.shape[self.spNum]), spNum = self.spNum, undo = revertSubpath } self.undo[#self.undo + 1] = t end end self:setShapeMarks() self.model.ui:update(false) -- update tool self:explain() end function EDITTOOL:mouseMove(button, modifiers) if self.moving then local pos = self.model.ui:pos() moveCP(self.shape, self.spNum, self.segNum, self.cpNum, pos) self:setShapeMarks() self.model.ui:update(false) -- update tool elseif self.scissor then local t t, self.scissorPos = self.scissor(self.model.ui:pos()) self:setShapeMarks() self.model.ui:update(false) -- update tool end self:explain() end function EDITTOOL:explain() if self.scissor then self.model.ui:explain("Left: cut | Right: menu | Ctrl+Z: undo | " .. "Space: accept") else self.model.ui:explain("Left: move | Right: menu | Ctrl+Z: undo | " .. "Space: accept") end end function EDITTOOL:acceptEdit() local t = { label="edit path", pno=self.model.pno, vno=self.model.vno, primary=self.primary, original=self.obj:clone(), final=self.obj:clone(), } t.final:setShape(self.shape) t.final:setMatrix(ipe.Matrix()) -- already in shape t.undo = function (t, doc) doc[t.pno]:replace(t.primary, t.original) end t.redo = function (t, doc) doc[t.pno]:replace(t.primary, t.final) end self.model:register(t) end function EDITTOOL:key(code, modifiers, text) -- print("Key:", code, text) if text == "\027" then -- Esc self.model.ui:finishTool() return true elseif code == 90 and modifiers.control then -- Ctrl+Z self.moving = false self.scissor = false self:action_undo() self:setShapeMarks() self.model.ui:update(false) -- update tool return true elseif code == 0x20 then -- Space: accept edit self.moving = false self:acceptEdit() self.model.ui:finishTool() return true else -- not consumed return false end end ---------------------------------------------------------------------- function MODEL:action_edit_path(prim, obj) EDITTOOL:new(self, prim, obj) end ---------------------------------------------------------------------- local join_threshold = 1e-9 local function flip(sub) sub[1], sub[2] = sub[2], sub[1] sub.flip = not sub.flip end local function findPartner(l, src, beg) local v = l[src][2] while beg <= #l do local w1 = l[beg][1] if (v - w1):sqLen() < join_threshold then return beg end local w2 = l[beg][2] if (v - w2):sqLen() < join_threshold then flip(l[beg]) return beg end beg = beg + 1 end return nil end local function reverse_segment(seg) local rseg = { type = seg.type } for i=#seg,1,-1 do rseg[#rseg + 1] = seg[i] -- copy control points in reverse order end if rseg.type == "arc" then -- need to do something special local alpha, beta = seg.arc:angles() rseg.arc = ipe.Arc(seg.arc:matrix() * ipe.Matrix(1, 0, 0, -1), beta, alpha) end return rseg end function MODEL:saction_join() local p = self:page() -- check that all objects consist of open subpaths only local l = {} for i,obj,sel,lay in p:objects() do if sel then if obj:type() ~= "path" then self:warning("Selection contains objects that are not paths.") return end local shape = obj:shape() transformShape(obj:matrix(), shape) for _,sp in ipairs(shape) do if sp.type ~= "curve" or sp.closed then self:warning("A selected object does not consist of open curves.") return end l[#l + 1] = { sp=sp, sp[1][1], sp[#sp][#sp[#sp]] } end end end if #l < 2 then self.ui:explain("only one path, nothing to join") return end -- match up endpoints if not findPartner(l, 1, 2) then -- not found, flip l[1] and try again flip(l[1]) end for i = 1,#l - 1 do -- invariant: l[1] .. l[i] form a chain local j = findPartner(l, i, i+1) if not j then self:warning("Cannot join paths", "Unable to join paths to a single curve") return end -- flip i+1 and j if j ~= i+1 then l[i+1], l[j] = l[j], l[i+1] end end -- now have a chain local nsp = { type = "curve", closed = false } for _, sp in ipairs(l) do if sp.flip then for i=#sp.sp,1,-1 do nsp[#nsp + 1] = reverse_segment(sp.sp[i]) -- because of rounding errors: if #nsp > 1 then nsp[#nsp][1] = nsp[#nsp - 1][#nsp[#nsp - 1]] end end else for i=1,#sp.sp do nsp[#nsp + 1] = sp.sp[i] -- because of rounding errors: if #nsp > 1 then nsp[#nsp][1] = nsp[#nsp - 1][#nsp[#nsp - 1]] end end end end -- check if it is closed if (nsp[1][1] - nsp[#nsp][#nsp[#nsp]]):sqLen() < join_threshold then nsp.closed = true if nsp[#nsp].type == "segment" then table.remove(nsp) end end local prim = p:primarySelection() local obj = p[prim]:clone() obj:setMatrix( ipe.Matrix() ) obj:setShape( { nsp } ) local t = { label = "join paths", pno = self.pno, vno = self.vno, selection = self:selection(), original = p:clone(), undo = revertOriginal, object = obj, layer = p:active(self.vno), } t.redo = function (t, doc) local p = doc[t.pno] for i = #t.selection,1,-1 do p:remove(t.selection[i]) end p:insert(nil, t.object, 1, t.layer) end self:register(t) end ---------------------------------------------------------------------- function MODEL:saction_compose() local p = self:page() local prim = p:primarySelection() local supershape = {} for i,obj,sel,lay in p:objects() do if sel then if obj:type() ~= "path" then self:warning("Cannot compose objects", "One of the selected objects is not a path object") return end local shape = obj:shape() if i ~= prim then transformShape(obj:matrix(), shape) transformShape(p[prim]:matrix():inverse(), shape) end for _,path in ipairs(shape) do supershape[#supershape + 1] = path end end end local obj = p[prim]:clone() obj:setShape(supershape) local t = { label = "compose paths", pno = self.pno, vno = self.vno, selection = self:selection(), original = p:clone(), undo = revertOriginal, object = obj, layer = p:active(self.vno), } t.redo = function (t, doc) local p = doc[t.pno] for i = #t.selection,1,-1 do p:remove(t.selection[i]) end p:insert(nil, t.object, 1, t.layer) end self:register(t) end ---------------------------------------------------------------------- function MODEL:saction_decompose() local p = self:page() local prim = p:primarySelection() if p[prim]:type() ~= "path" then self:warning("Cannot decompose objects", "Primary selection is not a path object") return end local shape = p[prim]:shape() if #shape <= 1 then self:warning("Cannot decompose objects", "Path object has only one subpath") return end transformShape(p[prim]:matrix(), shape) local objects = {} for _,path in ipairs(shape) do objects[#objects + 1] = ipe.Path(self.attributes, { path }) end local t = { label = "decompose path", pno = self.pno, vno = self.vno, primary = prim, original = p:clone(), undo = revertOriginal, objects = objects, layer = p:active(self.vno), } t.redo = function (t, doc) local p = doc[t.pno] p:remove(t.primary) for _,obj in ipairs(t.objects) do p:insert(nil, obj, 2, t.layer) end p:ensurePrimarySelection() end p:deselectAll() self:register(t) end ---------------------------------------------------------------------- ipe-7.1.4/src/ipe/lua/prefs.lua0000644000175000017500000001441512120621776016132 0ustar otfriedotfried---------------------------------------------------------------------- -- Ipe preference settings ---------------------------------------------------------------------- --[[ This file is part of the extensible drawing editor Ipe. Copyright (C) 1993-2013 Otfried Cheong Ipe is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. As a special exception, you have permission to link Ipe with the CGAL library and distribute executables, as long as you follow the requirements of the Gnu General Public License in regard to all of the software in the executable aside from CGAL. Ipe 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 General Public License for more details. You should have received a copy of the GNU General Public License along with Ipe; if not, you can find it at "http://www.gnu.org/copyleft/gpl.html", or write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. --]] local home = os.getenv("HOME") prefs = {} -- List of stylesheets that are added to newly created docs. Without -- a full path, stylesheets are searched for in the standard style -- directory. prefs.styles = { "basic" } -- Interval for autosaving in seconds -- set to nil to disable autosaving prefs.autosave_interval = 600 -- 10 minutes -- Filename for autosaving -- can contain '%s' for the filename of the current file -- can use 'home' for the user's home directory -- prefs.autosave_filename = home .. "/autosave.ipe" if config.platform == "win" then prefs.autosave_filename = "C:%s.autosave" else prefs.autosave_filename = home .. "/%s.autosave" end -- External editor for editing text objects -- must contain '%s' for the temporary filename -- set this to nil to hide the "Editor" button on text dialogs -- by default this is disabled on Windows as a -- DOS window will pop up when calling the editor if os.getenv("EDITOR") then prefs.external_editor = os.getenv("EDITOR") .. " %s" elseif config.platform == "unix" then prefs.external_editor = "gedit %s" -- prefs.external_editor = "emacsclient %s" else prefs.external_editor = nil end -- Should LaTeX be run automatically every time text has changed? prefs.auto_run_latex = true -- Should the external editor be called automatically? prefs.auto_external_editor = nil -- Size of dialog window for creating/editing text objects prefs.editor_size = { 600, 400 } -- Size of main window at startup prefs.window_size = { 1000, 600 } -- Size of page sorter window prefs.page_sorter_size = { 960, 600 } -- Width of page thumbnails (height is computed automatically) prefs.thumbnail_width = 300 -- Canvas customization: prefs.canvas_style = { paper_color = { r = 1.0, g = 1.0, b = 1.0 }, -- white -- paper_color = { r = 1.0, g = 1.0, b = 0.5 } -- classic Ipe 6 yellow -- classic grid uses dots instead of lines classic_grid = false, -- line width of grid lines -- if classic_grid is true, then thin_grid_lines is size of grid dots thin_grid_line = 0.1, thick_grid_line = 0.3, -- steps indicate multiples of grid distance where grid lines are drawn thin_step = 1, thick_step = 4, -- e.g. try this: thin_step = 2, thick_step = 5 } -- Should the grid be visible when Ipe starts? (true or false) prefs.grid_visible = true -- Snap modes active when Ipe starts: prefs.snap = { vertex = false, boundary = false, intersection = false, grid = true, angle = false, autoangle = false } -- Initial grid size and angle prefs.grid_size = 16 -- points prefs.angle_size = 45 -- degrees -- Maximum distance in pixels selecting/snapping prefs.select_distance = 36 prefs.snap_distance = 16 -- When transforming objects, if currently select object is further than -- this distance, the closest object is selected instead prefs.close_distance = 48 -- Zoom factors, minimal and maximal possible zoom prefs.zoom_factor = 1.3 prefs.wheel_zoom_factor = 1.3 -- used when zooming by scroll wheel prefs.min_zoom = 0.1 prefs.max_zoom = 100 -- Should newly created text be transformable by default? prefs.text_transformable = false -- If set to true, then whenever the user edits the title of a page, -- the check box "section: use title" is checked automatically. prefs.automatic_use_title = false -- How to start browser to show Ipe manual if config.platform == "apple" then prefs.browser = "open %s" else -- 'sensible-browser' and 'gnome-open' both work on Linux -- prefs.browser = "sensible-browser %s &" prefs.browser = "gnome-open %s" end -- How to start onscreen keyboard -- prefs.keyboard = "onboard &" prefs.keyboard = nil -- tablet mode (true or false) -- If tablet_mode is true, then the current selection is not highlighted -- when in "ink" drawing mode. -- All snap modes are disabled when "ink" drawing mode is started. prefs.tablet_mode = false -- Extended properties menu, perhaps useful for tablets: prefs.tablet_menu = false -- format string for the coordinates in the status bar -- (x, unit, y, unit) -- prefs.coordinates_format = "%g%s, %g%s" prefs.coordinates_format = "[%7.3f%s, %7.3f%s]" -- possible scale factors for coordinates output -- must be integers. -5 means "5:1", +5 means "1:5" prefs.scale_factors = { -100, -5, 10, 100, 1000, 10000 } -- Auto-exporting when document is being saved -- if auto_export_only_if_exists is true, then the file will only -- be auto-exported if a file with the target name already exists prefs.auto_export_xml_to_eps = false prefs.auto_export_xml_to_pdf = false prefs.auto_export_eps_to_pdf = false prefs.auto_export_pdf_to_eps = false prefs.auto_export_only_if_exists = true -- Default directory for "Save as" dialog, when -- the current document does not have a filename -- (or the filename is not absolute) -- If you use Ipe from the commandline, "." is the right value. prefs.save_as_directory = "." -- Otherwise, you could use the home directory, or Documents: -- prefs.save_as_directory = home -- prefs.save_as_directory = home .. "/Documents" ---------------------------------------------------------------------- ipe-7.1.4/src/ipe/lua/properties.lua0000644000175000017500000003745312120621776017216 0ustar otfriedotfried---------------------------------------------------------------------- -- properties.lua ---------------------------------------------------------------------- --[[ This file is part of the extensible drawing editor Ipe. Copyright (C) 1993-2013 Otfried Cheong Ipe is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. As a special exception, you have permission to link Ipe with the CGAL library and distribute executables, as long as you follow the requirements of the Gnu General Public License in regard to all of the software in the executable aside from CGAL. Ipe 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 General Public License for more details. You should have received a copy of the GNU General Public License along with Ipe; if not, you can find it at "http://www.gnu.org/copyleft/gpl.html", or write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. --]] local function color_icon(sheets, name) local abs = sheets:find("color", name) if abs then return abs.r, abs.g, abs.b end return 0.0, 0.0, 0.0 end function MODEL:propertiesPopup() self:updateCloseSelection(false) local sel = self:selection() if #sel > 1 then self:multiPopup(sel) elseif #sel == 0 then self:emptyPopup() else self:singlePopup(self:page():primarySelection()) end end function MODEL:emptyPopup() local m = ipeui.Menu(self.ui:win()) m:add("action_paste_at_cursor", "Paste at cursor") m:add("action_pan_here", "Pan canvas") m:add("grid", "Toggle grid") local gp = self.ui:globalPos() local item, num, value = m:execute(gp.x, gp.y) if item then if item:sub(1,7) == "action_" then self:action(item:sub(8)) elseif item == "grid" then self:toggleGrid() end end end function MODEL:singlePopup(prim) local obj = self:page()[prim] local m = ipeui.Menu(self.ui:win()) self["properties_" .. obj:type()](self, obj, m) if prefs.tablet_menu then m:add("action_cut", "Cut") m:add("action_copy", "Copy") m:add("action_paste_at_cursor", "Paste at cursor") m:add("action_pan_here", "Pan canvas") m:add("grid", "Toggle grid") end local gp = self.ui:globalPos() local item, num, value = m:execute(gp.x, gp.y) if item then if item == "layer" then self:changeLayerOfPrimary(prim, value) elseif item:sub(1,7) == "action_" then self:action(item:sub(8)) elseif item == "comment" then -- nothing to do elseif item == "grid" then self:toggleGrid() else self:setAttributeOfPrimary(prim, item, value) end end end -------------------------------------------------------------------- function MODEL:toggleGrid() local t = not self.ui:actionState("grid_visible"); self.ui:setActionState("grid_visible", t) self:action_grid_visible() end function MODEL:changeLayerOfPrimary(prim, layer) local p = self:page() local t = { label="change layer to " .. layer, pno=self.pno, vno=self.vno, primary=prim, original=p:layerOf(prim), toLayer=layer, } t.undo = function (t, doc) doc[t.pno]:setLayerOf(t.primary, t.original) end t.redo = function (t, doc) doc[t.pno]:setLayerOf(t.primary, t.toLayer) end self:register(t) end function MODEL:setAttributeOfPrimary(prim, prop, value) self:deselectSecondary() local p = self:page() local t = { label="set attribute " .. prop .. " to " .. tostring(value), pno=self.pno, vno=self.vno, primary=prim, original=p[prim]:clone(), property=prop, value=value, stroke=self.attributes.stroke, fill=self.attributes.fill, } t.undo = function (t, doc) doc[t.pno]:replace(t.primary, t.original) end t.redo = function (t, doc) doc[t.pno]:setAttribute(t.primary, t.property, t.value, t.stroke, t.fill) end self:register(t) if prop == "minipage" or prop == "textsize" or prop == "textstyle" then self:autoRunLatex() end end ---------------------------------------------------------------------- function MODEL:insertBasic(m, obj) local p = self:page() local layerL = p:layers() local pinnedL = { "none", "horizontal", "vertical", "fixed" } local transformationsL = { "translations", "rigid", "affine" } local layer = p:layerOf(p:primarySelection()) local pinned = obj:get("pinned") local transformations = obj:get("transformations") m:add("layer", "Layer: " .. layer, layerL, nil, layer) m:add("pinned", "Pinned: " .. pinned, pinnedL, nil, pinned) m:add("transformations", "Transformations: " .. transformations, transformationsL, nil, transformations) end function MODEL:insertOpacity(m, obj) local opacityL = self.doc:sheets():allNames("opacity") local opacity = obj:get("opacity") m:add("opacity", "Opacity: " .. opacity, opacityL, nil, opacity) end ---------------------------------------------------------------------- function MODEL:properties_group(obj, m) m:add("comment", "Group object") local s = string.format("%d elements", obj:count()) local clip = obj:clip() if clip then s = s .. ", with clipping" end m:add("comment", s) self:insertBasic(m, obj) if clip then m:add("action_remove_clipping", "Remove clipping") m:add("action_extract_clipping", "Extract clipping path") end m:add("action_edit_as_xml", "Edit as XML") m:add("action_ungroup", "Ungroup") end function MODEL:properties_path(obj, m) local sheet = self.doc:sheets() local colors = sheet:allNames("color") local pathmodes = { "stroke only", "stroke && fill", "fill only" } local pathmodeL = { "stroked", "strokedfilled", "filled" } local penL = sheet:allNames("pen") local dashstyleL = sheet:allNames("dashstyle") local arrowsizeL = sheet:allNames("arrowsize") local arrowshapeL = symbolNames(sheet, "arrow/", "(spx)") local tilingL = sheet:allNames("tiling") table.insert(tilingL, 1, "normal") local gradientL = sheet:allNames("gradient") table.insert(gradientL, 1, "normal") local linecapL = { "normal", "butt", "round", "square", } local linejoinL = { "normal", "miter", "round", "bevel", } local fillruleL = { "normal", "wind", "evenodd", } local shape = obj:shape() m:add("comment", "Path object") m:add("comment", string.format("%d subpaths", #shape)) self:insertBasic(m, obj) local pm = obj:get("pathmode") m:add("pathmode", "Stroke && Fill: " .. pathmodes[indexOf(pm, pathmodeL)], pathmodeL, pathmodes, pm) if pm ~= "filled" then m:add("stroke", "Stroke color: " .. colorString(obj:get("stroke")), colors, nil, function (i, name) return color_icon(self.doc:sheets(), name) end) end if pm ~= "stroked" then m:add("fill", "Fill color: " .. colorString(obj:get("fill")), colors, nil, function (i, name) return color_icon(self.doc:sheets(), name) end) end local pen = obj:get("pen") m:add("pen", "Pen width: " .. pen, penL, nil, pen) local dashstyle = obj:get("dashstyle") m:add("dashstyle", "Dash style: " .. dashstyle, dashstyleL, nil, dashstyle) local farr = obj:get("farrow") local rarr = obj:get("rarrow") local boolnames = { "yes", "no" } local boolmap = { "true", "false" } local bool_to_yesno = { [false]="no", [true]="yes" } m:add("farrow", "Forward arrow: " .. bool_to_yesno[farr], boolmap, boolnames, tostring(farr)) if farr then m:add("farrowsize", "Forward arrow size", arrowsizeL, nil, obj:get("farrowsize")) m:add("farrowshape", "Forward arrow shape", arrowshapeL, arrowshapeToName, obj:get("farrowshape")) end m:add("rarrow", "Reverse arrow: " .. bool_to_yesno[rarr], boolmap, boolnames, tostring(rarr)) if rarr then m:add("rarrowsize", "Reverse arrow size", arrowsizeL, nil, obj:get("rarrowsize")) m:add("rarrowshape", "Reverse arrow shape", arrowshapeL, arrowshapeToName, obj:get("rarrowshape")) end local lc = obj:get("linecap") local lj = obj:get("linejoin") local fr = obj:get("fillrule") m:add("linecap", "Line cap: " .. lc, linecapL, nil, lc) m:add("linejoin", "Line join: " .. lj, linejoinL, nil, lj) m:add("fillrule", "Fill rule: " .. fr, fillruleL, nil, fr) if pm ~= "stroked" then local tiling = obj:get("tiling") local gradient = obj:get("gradient") m:add("tiling", "Tiling pattern: " .. tiling, tilingL, nil, tiling) m:add("gradient", "Gradient: " .. gradient, gradientL, nil, gradient) end self:insertOpacity(m, obj) if #shape > 1 then m:add("action_decompose", "Decompose path") end m:add("action_edit_as_xml", "Edit as XML") m:add("action_edit", "Edit path") end function MODEL:properties_text(obj, m) local sheet = self.doc:sheets() local minipage = obj:get("minipage") local colors = sheet:allNames("color") local textsizeL = sheet:allNames("textsize") local textstyleL = sheet:allNames("textstyle") m:add("comment", "Text object") self:insertBasic(m, obj) local t = minipage and "minipage" or "label" m:add("minipage", "Type: " .. t, {"true", "false"}, {"minipage", "label"}, tostring(minipage)) m:add("stroke", "Color: " .. colorString(obj:get("stroke")), colors, nil, function (i, name) return color_icon(self.doc:sheets(), name) end) local ts = obj:get("textsize") m:add("textsize", "Size: " .. ts, textsizeL, nil, ts) if minipage then local ts = obj:get("textstyle") m:add("textstyle", "Style: " .. ts, textstyleL, nil, ts) else local ha = obj:get("horizontalalignment") m:add("horizontalalignment", "Horizontal alignment: " .. ha, {"left", "right", "hcenter"}, nil, ha) end local va = obj:get("verticalalignment") m:add("verticalalignment", "Vertical alignment: " .. va, {"bottom", "baseline", "top", "vcenter"}, nil, va) self:insertOpacity(m, obj) if minipage then m:add("action_change_width", "Change width") end m:add("action_edit_as_xml", "Edit as XML") m:add("action_edit", "Edit text") end function MODEL:properties_image(obj, m) m:add("comment", "Image object") local info = obj:info() m:add("comment", string.format("%d x %d pixels", info.width, info.height)) m:add("comment", string.format("%d components with %d bits", info.components, info.bitsPerComponent)) m:add("comment", "Filter " .. info.filter) self:insertBasic(m, obj) end function MODEL:properties_reference(obj, m) local sheet = self.doc:sheets() local colors = sheet:allNames("color") local sizes = sheet:allNames("symbolsize") local pens = sheet:allNames("pen") m:add("comment", "Reference object") m:add("comment", "Symbol name: " .. obj:symbol()) self:insertBasic(m, obj) m:add("stroke", "Stroke color: " .. colorString(obj:get("stroke")), colors, nil, function (i, name) return color_icon(self.doc:sheets(), name) end) m:add("fill", "Fill color: " .. colorString(obj:get("fill")), colors, nil, function (i, name) return color_icon(self.doc:sheets(), name) end) local ss = obj:get("symbolsize") m:add("symbolsize", "Size: " .. ss, sizes, nil, ss) local pen = obj:get("pen") m:add("pen", "Pen: " .. pen, pens, nil, pen) m:add("action_edit_as_xml", "Edit as XML") end ---------------------------------------------------------------------- local object_name = { text = "Text", path = "Path", image = "Image", reference = "Reference", group = "Group", } function MODEL:multiAttributes(m, tm) local layers = self:page():layers() local pinned = { "none", "horizontal", "vertical", "fixed" } local transformations = { "translations", "rigid", "affine" } m:add("layer", "Layer", layers) m:add("pinned", "Pinned", pinned) m:add("transformations", "Transformations", transformations) local sheet = self.doc:sheets() local colors = sheet:allNames("color") local sizes = sheet:allNames("symbolsize") local pens = sheet:allNames("pen") local opacity = sheet:allNames("opacity") local pathmodes = { "stroke only", "stroke && fill", "fill only" } local pathmode = { "stroked", "strokedfilled", "filled" } local dashstyle = sheet:allNames("dashstyle") local arrowsizes = sheet:allNames("arrowsize") local arrowshapes = symbolNames(sheet, "arrow/", "(spx)") local tilings = sheet:allNames("tiling") table.insert(tilings, 1, "normal") local gradients = sheet:allNames("gradient") table.insert(gradients, 1, "normal") local linecap = { "normal", "butt", "round", "square", } local linejoin = { "normal", "miter", "round", "bevel", } local fillrule = { "normal", "wind", "evenodd", } local textsize = sheet:allNames("textsize") local textstyle = sheet:allNames("textstyle") if tm.path or tm.text or tm.reference then m:add("stroke", "Stroke color", colors, nil, function (i, name) return color_icon(sheet, name) end) end if tm.path or tm.reference then m:add("fill", "Fill color", colors, nil, function (i, name) return color_icon(sheet, name) end) end if tm.path or tm.reference then m:add("pen", "Pen width", pens) end if tm.path then m:add("pathmode", "Stroke && Fill", pathmode, pathmodes) m:add("dashstyle", "Dash style", dashstyle) local boolnames = { "yes", "no" } local boolmap = { "true", "false" } m:add("farrow", "Forward arrow", boolmap, boolnames) m:add("farrowsize", "Forward arrow size", arrowsizes) m:add("farrowshape", "Forward arrow shape", arrowshapes, arrowshapeToName) m:add("rarrow", "Reverse arrow", boolmap, boolnames) m:add("rarrowsize", "Reverse arrow size", arrowsizes) m:add("rarrowshape", "Reverse arrow shape", arrowshapes, arrowshapeToName) m:add("linecap", "Line cap", linecap) m:add("linejoin", "Line join", linejoin) m:add("fillrule", "Fill rule", fillrule) m:add("tiling", "Tiling pattern", tilings) m:add("gradient", "Gradient", gradients) end if tm.text then m:add("textsize", "Text size", textsize) m:add("textstyle", "Text style", textstyle) m:add("horizontalalignment", "Horizontal alignment", {"left", "right", "hcenter"}) m:add("verticalalignment", "Vertical alignment", {"bottom", "baseline", "top", "vcenter"}) end if tm.reference then m:add("symbolsize", "Size", sizes) end if tm.text or tm.path then m:add("opacity", "Opacity", opacity) end end function MODEL:multiPopup() -- collect types of selected objects local p = self:page() local typmap = {} local count = 0 for i,obj,sel,layer in self:page():objects() do if sel then typmap[obj:type()] = true; count = count + 1 end end local typcount = 0 local ttype = nil for t in pairs(typmap) do typcount = typcount + 1; ttype = t end local m = ipeui.Menu(self.ui:win()) if typcount == 1 then m:add("comment", string.format("%d %s objects", count, object_name[ttype])) else m:add("comment", string.format("%d objects", count)) end self:multiAttributes(m, typmap) if count == 2 and typcount == 2 and typmap["group"] and typmap["path"] then m:add("action_add_clipping", "Add clipping path") end if typcount == 1 and ttype == 'path' then m:add("action_join", "Join paths") m:add("action_compose", "Compose paths") end if prefs.tablet_menu then m:add("action_cut", "Cut") m:add("action_copy", "Copy") m:add("action_paste_at_cursor", "Paste at cursor") m:add("action_pan_here", "Pan canvas") m:add("grid", "Toggle grid") end local gp = self.ui:globalPos() local item, num, value = m:execute(gp.x, gp.y) if item then if item == "layer" then self:action_move_to_layer(value) elseif item:sub(1,7) == "action_" then self:action(item:sub(8)) elseif item == "comment" then -- nothing to do elseif item == "grid" then self:toggleGrid() else self:setAttribute(item, value) end end end -------------------------------------------------------------------- ipe-7.1.4/src/ipe/lua/tools.lua0000644000175000017500000010235112120621776016150 0ustar otfriedotfried---------------------------------------------------------------------- -- tools.lua ---------------------------------------------------------------------- --[[ This file is part of the extensible drawing editor Ipe. Copyright (C) 1993-2013 Otfried Cheong Ipe is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. As a special exception, you have permission to link Ipe with the CGAL library and distribute executables, as long as you follow the requirements of the Gnu General Public License in regard to all of the software in the executable aside from CGAL. Ipe 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 General Public License for more details. You should have received a copy of the GNU General Public License along with Ipe; if not, you can find it at "http://www.gnu.org/copyleft/gpl.html", or write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. --]] function externalEditor(d, field) local text = d:get(field) local fname = os.tmpname() local f = io.open(fname, "w") f:write(text) f:close() ipeui.WaitDialog(string.format(prefs.external_editor, fname)) f = io.open(fname, "r") text = f:read("*all") f:close() os.remove(fname) d:set(field, text) end function addEditorField(d, field) if prefs.external_editor then d:addButton("editor", "&Editor", function (d) externalEditor(d, field) end) end end ---------------------------------------------------------------------- local function circleshape(center, radius) return { type="ellipse"; ipe.Matrix(radius, 0, 0, radius, center.x, center.y) } end local function segmentshape(v1, v2) return { type="curve", closed=false; { type="segment"; v1, v2 } } end local function boxshape(v1, v2) return { type="curve", closed=true; { type="segment"; v1, V(v1.x, v2.y) }, { type="segment"; V(v1.x, v2.y), v2 }, { type="segment"; v2, V(v2.x, v1.y) } } end local function arcshape(center, radius, alpha, beta) local a = ipe.Arc(ipe.Matrix(radius, 0, 0, radius, center.x, center.y), alpha, beta) local v1 = center + radius * ipe.Direction(alpha) local v2 = center + radius * ipe.Direction(beta) return { type="curve", closed=false; { type="arc", arc=a; v1, v2 } } end local function rarcshape(center, radius, alpha, beta) local a = ipe.Arc(ipe.Matrix(radius, 0, 0, -radius, center.x, center.y), alpha, beta) local v1 = center + radius * ipe.Direction(alpha) local v2 = center + radius * ipe.Direction(beta) return { type="curve", closed=false; { type="arc", arc=a; v1, v2 } } end ---------------------------------------------------------------------- local VERTEX = 1 local SPLINE = 2 local QUAD = 3 local BEZIER = 4 local ARC = 5 LINESTOOL = {} LINESTOOL.__index = LINESTOOL -- mode is one of "lines", "polygons", "splines" function LINESTOOL:new(model, mode) local tool = {} setmetatable(tool, LINESTOOL) tool.model = model tool.mode = mode local v = model.ui:pos() tool.v = { v, v } model.ui:setAutoOrigin(v) if mode == "splines" then tool.t = { VERTEX, SPLINE } else tool.t = { VERTEX, VERTEX } end model.ui:shapeTool(tool) tool.setColor(1.0, 0, 0) return tool end function LINESTOOL:last() return self.t[#self.t] end function LINESTOOL:has_segs(count) if #self.t < count then return false end local result = true for i = #self.t - count + 1,#self.t do if self.t[i] ~= VERTEX then return false end end return true end local function compute_arc(p0, pmid, p1) if p0 == p1 then return { type="segment", p0, p1 } end local l1 = ipe.Line(p0, (pmid- p0):normalized()) local l2 = ipe.Line(p0, l1:normal()) local bi1 = ipe.Bisector(p0, p1) local center = l2:intersects(bi1) local side = l1:side(p1) if side == 0.0 or not center then return { type="segment", p0, p1 } end local u = p0 - center local alpha = side * u:angle() local beta = side * ipe.normalizeAngle((p1 - center):angle(), alpha) local radius = u:len() local m = { radius, 0, 0, side * radius, center.x, center.y } return { type = "arc", p0, p1, arc = ipe.Arc(ipe.Matrix(m), alpha, beta) } end -- compute orientation of tangent to previous segment at its final point function LINESTOOL:compute_orientation() if self.t[#self.t - 2] ~= ARC then return (self.v[#self.v - 1] - self.v[#self.v - 2]):angle() else -- only arc needs special handling local arc = compute_arc(self.v[#self.v - 3], self.v[#self.v - 2], self.v[#self.v - 1]) if arc.type == "arc" then local alpha, beta = arc.arc:angles() local dir = ipe.Direction(beta + math.pi / 2) return (arc.arc:matrix():linear() * dir):angle() else return (self.v[#self.v - 1] - self.v[#self.v - 3]):angle() end end end function LINESTOOL:compute() self.shape = { type="curve", closed=(self.mode == "polygons") } local i = 2 while i <= #self.v do -- invariant: t[i-1] == VERTEX local seg if self.t[i] == VERTEX then seg = { type="segment", self.v[i-1], self.v[i] } i = i + 1 elseif self.t[i] == SPLINE then local j = i while j <= #self.v and self.t[j] == SPLINE do j = j + 1 end if j > #self.v then j = #self.v end seg = { type="spline" } for k = i-1,j do seg[#seg+1] = self.v[k] end i = j + 1 elseif self.t[i] == QUAD then seg = { type="quad", self.v[i-1], self.v[i], self.v[i+1] } i = i + 2 elseif self.t[i] == BEZIER then seg = { type="bezier", self.v[i-1], self.v[i], self.v[i+1], self.v[i+2] } i = i + 3 elseif self.t[i] == ARC then seg = compute_arc(self.v[i-1], self.v[i], self.v[i+1]) i = i + 2 end self.shape[#self.shape + 1] = seg end self.setShape( { self.shape } ) end function LINESTOOL:mouseButton(button, modifiers, press) if not press then return end local v = self.model.ui:pos() self.v[#self.v] = v if button == 2 then if self:last() == SPLINE then self.t[#self.t] = VERTEX end self:compute() self.model.ui:finishTool() local obj = ipe.Path(self.model.attributes, { self.shape }, true) -- if it is just a point, force line cap to round if #self.shape == 1 and self.shape[1].type == "segment" and self.shape[1][1] == self.shape[1][2] then obj:set("linecap", "round") end self.model:creation("create path", obj) return end self.v[#self.v + 1] = v self.model.ui:setAutoOrigin(v) if self:last() == SPLINE then local typ = modifiers.shift and VERTEX or SPLINE self.t[#self.t] = typ self.t[#self.t + 1] = typ else self.t[#self.t + 1] = VERTEX end self:compute() self.model.ui:update(false) -- update tool self:explain() end function LINESTOOL:mouseMove() self.v[#self.v] = self.model.ui:pos() self:compute() self.model.ui:update(false) -- update tool self:explain() end function LINESTOOL:explain() local s if self:last() == SPLINE then s = ("Left: add ctrl point | Shift+Left: switch to line mode" .. " | Del: delete ctrl point") else s = "Left: add vtx | Del: delete vtx" end s = s .. " | Right: final vtx" if self:has_segs(2) then s = s .. " | " .. shortcuts_linestool.spline .. ": spline mode" end if self:has_segs(3) then s = s .. " | " .. shortcuts_linestool.quadratic_bezier .. ": quadratic Bezier" s = s .. " | " .. shortcuts_linestool.arc .. ": circle arc" end if self:has_segs(4) then s = s .. " | " .. shortcuts_linestool.cubic_bezier ..": cubic Bezier" end if #self.v > 2 and self.t[#self.t - 1] == VERTEX then s = s .. " | " .. shortcuts_linestool.set_axis ..": set axis" end self.model.ui:explain(s, 0) end function LINESTOOL:key(code, modifiers, text) if text == "\127" then -- Delete if #self.v > 2 then table.remove(self.v) table.remove(self.t) if self:last() == QUAD or self:last() == ARC then self.t[#self.t] = VERTEX end if self:last() == BEZIER then self.t[#self.t] = VERTEX self.t[#self.t-1] = VERTEX end self:compute() self.model.ui:update(false) self:explain() else self.model.ui:finishTool() end return true elseif text == "\027" then self.model.ui:finishTool() return true elseif self:has_segs(2) and text == shortcuts_linestool.spline then self.t[#self.t] = SPLINE self:compute() self.model.ui:update(false) self:explain() elseif self:has_segs(3) and text == shortcuts_linestool.quadratic_bezier then self.t[#self.t - 1] = QUAD self:compute() self.model.ui:update(false) self:explain() elseif self:has_segs(3) and text == shortcuts_linestool.arc then self.t[#self.t - 1] = ARC self:compute() self.model.ui:update(false) self:explain() elseif self:has_segs(4) and text == shortcuts_linestool.cubic_bezier then self.t[#self.t - 1] = BEZIER self.t[#self.t - 2] = BEZIER self:compute() self.model.ui:update(false) self:explain() elseif #self.v > 2 and self.t[#self.t - 1] == VERTEX and text == shortcuts_linestool.set_axis then -- set axis self.model.snap.with_axes = true self.model.snap.snapangle = true self.model.snap.origin = self.v[#self.v - 1] self.model.snap.orientation = self:compute_orientation() self.model.ui:setSnap(self.model.snap) self.model.ui:setActionState("snapangle", true) self.model.ui:update(true) -- redraw coordinate system self:explain() else return false end end ---------------------------------------------------------------------- BOXTOOL = {} BOXTOOL.__index = BOXTOOL function BOXTOOL:new(model, square) local tool = {} setmetatable(tool, BOXTOOL) tool.model = model tool.square = square local v = model.ui:pos() tool.v = { v, v } model.ui:shapeTool(tool) tool.setColor(1.0, 0, 0) return tool end function BOXTOOL:compute() self.v[2] = self.model.ui:pos() if self.square then local d = self.v[2] - self.v[1] local sign = V(d.x > 0 and 1 or -1, d.y > 0 and 1 or -1) local dd = math.max(math.abs(d.x), math.abs(d.y)) self.v[2] = self.v[1] + dd * sign end self.shape = boxshape(self.v[1], self.v[2]) end function BOXTOOL:mouseButton(button, modifiers, press) if not press then return end self:compute() self.model.ui:finishTool() local obj = ipe.Path(self.model.attributes, { self.shape }) self.model:creation("create box", obj) end function BOXTOOL:mouseMove() self:compute() self.setShape( { self.shape } ) self.model.ui:update(false) -- update tool end function BOXTOOL:key(code, modifiers, text) if text == "\027" then self.model.ui:finishTool() return true else return false end end ---------------------------------------------------------------------- SPLINEGONTOOL = {} SPLINEGONTOOL.__index = SPLINEGONTOOL function SPLINEGONTOOL:new(model) local tool = {} setmetatable(tool, SPLINEGONTOOL) tool.model = model local v = model.ui:pos() tool.v = { v, v } model.ui:shapeTool(tool) tool.setColor(1.0, 0, 0) return tool end function SPLINEGONTOOL:compute() if #self.v == 2 then self.shape = segmentshape(self.v[1], self.v[2]) else self.shape = { type="closedspline" } for _,v in ipairs(self.v) do self.shape[#self.shape + 1] = v end end self.setShape( { self.shape } ) end function SPLINEGONTOOL:explain() local s = "Left: Add vertex | Right: Add final vertex | Del: Delete vertex" self.model.ui:explain(s, 0) end function SPLINEGONTOOL:mouseButton(button, modifiers, press) if not press then return end local v = self.model.ui:pos() self.v[#self.v] = v if button == 2 then self.model.ui:finishTool() local obj = ipe.Path(self.model.attributes, { self.shape }) self.model:creation("create splinegon", obj) return end self.v[#self.v + 1] = v self:compute() self.model.ui:update(false) -- update tool self:explain() end function SPLINEGONTOOL:mouseMove() self.v[#self.v] = self.model.ui:pos() self:compute() self.model.ui:update(false) -- update tool end function SPLINEGONTOOL:key(code, modifiers, text) if text == "\127" then -- Delete if #self.v > 2 then table.remove(self.v) self:compute() self.model.ui:update(false) self:explain() else self.model.ui:finishTool() end return true elseif text == "\027" then self.model.ui:finishTool() return true else self:explain() return false end end ---------------------------------------------------------------------- CIRCLETOOL = {} CIRCLETOOL.__index = CIRCLETOOL function CIRCLETOOL:new(model, mode) local tool = {} setmetatable(tool, CIRCLETOOL) tool.model = model tool.mode = mode local v = model.ui:pos() tool.v = { v, v, v } tool.cur = 2 model.ui:shapeTool(tool) tool.setColor(1.0, 0, 0) return tool end function CIRCLETOOL:compute() if self.mode == "circle1" then self.shape = circleshape(self.v[1], (self.v[2] - self.v[1]):len()) elseif self.mode == "circle2" then self.shape = circleshape(0.5 * (self.v[1] + self.v[2]), (self.v[2] - self.v[1]):len() / 2.0) elseif self.mode == "circle3" then if self.cur == 2 or self.v[3] == self.v[2] then self.shape = circleshape(0.5 * (self.v[1] + self.v[2]), (self.v[2] - self.v[1]):len() / 2.0) else local l1 = ipe.LineThrough(self.v[1], self.v[2]) if math.abs(l1:side(self.v[3])) < 1e-9 then self.shape = segmentshape(self.v[1], self.v[2]) else local l2 = ipe.LineThrough(self.v[2], self.v[3]) local bi1 = ipe.Bisector(self.v[1], self.v[2]) local bi2 = ipe.Bisector(self.v[2], self.v[3]) local center = bi1:intersects(bi2) self.shape = circleshape(center, (self.v[1] - center):len()) end end end end function CIRCLETOOL:mouseButton(button, modifiers, press) if not press then return end local v = self.model.ui:pos() -- refuse point identical to previous if v == self.v[self.cur - 1] then return end self.v[self.cur] = v self:compute() if self.cur == 3 or (self.mode ~= "circle3" and self.cur == 2) then self.model.ui:finishTool() local obj = ipe.Path(self.model.attributes, { self.shape }) self.model:creation("create circle", obj) else self.cur = self.cur + 1 self.model.ui:update(false) end end function CIRCLETOOL:mouseMove() self.v[self.cur] = self.model.ui:pos() self:compute() self.setShape({ self.shape }) self.model.ui:update(false) -- update tool end function CIRCLETOOL:key(code, modifiers, text) if text == "\027" then self.model.ui:finishTool() return true else return false end end ---------------------------------------------------------------------- ARCTOOL = {} ARCTOOL.__index = ARCTOOL function ARCTOOL:new(model, mode) local tool = {} setmetatable(tool, ARCTOOL) tool.model = model tool.mode = mode local v = model.ui:pos() tool.v = { v, v, v } tool.cur = 2 model.ui:shapeTool(tool) tool.setColor(1.0, 0, 0) return tool end function ARCTOOL:compute() local u = self.v[2] - self.v[1] if self.cur == 2 then if self.mode == "arc3" then self.shape = circleshape(0.5 * (self.v[1] + self.v[2]), u:len() / 2.0) else self.shape = circleshape(self.v[1], u:len()) end return end local alpha = u:angle() local beta = (self.v[3] - self.v[1]):angle() if self.mode == "arc1" then self.shape = arcshape(self.v[1], u:len(), alpha, beta) elseif self.mode == "arc2" then self.shape = rarcshape(self.v[1], u:len(), alpha, beta) else local l1 = ipe.LineThrough(self.v[1], self.v[2]) if math.abs(l1:side(self.v[3])) < 1e-9 or self.v[3] == self.v[2] then self.shape = segmentshape(self.v[1], self.v[2]) else local l2 = ipe.LineThrough(self.v[2], self.v[3]) local bi1 = ipe.Line(0.5 * (self.v[1] + self.v[2]), l1:normal()) local bi2 = ipe.Line(0.5 * (self.v[2] + self.v[3]), l2:normal()) local center = bi1:intersects(bi2) u = self.v[1] - center alpha = u:angle() beta = ipe.normalizeAngle((self.v[2] - center):angle(), alpha) local gamma = ipe.normalizeAngle((self.v[3] - center):angle(), alpha) if gamma > beta then self.shape = arcshape(center, u:len(), alpha, gamma) else self.shape = rarcshape(center, u:len(), alpha, gamma) end end end end function ARCTOOL:mouseButton(button, modifiers, press) if not press then return end local v = self.model.ui:pos() -- refuse point identical to previous if v == self.v[self.cur - 1] then return end self.v[self.cur] = v self:compute() if self.cur == 3 then self.model.ui:finishTool() local obj = ipe.Path(self.model.attributes, { self.shape }, true) self.model:creation("create arc", obj) else self.cur = self.cur + 1 self.model.ui:update(false) end end function ARCTOOL:mouseMove() self.v[self.cur] = self.model.ui:pos() self:compute() self.setShape({ self.shape }) self.model.ui:update(false) -- update tool end function ARCTOOL:key(code, modifiers, text) if text == "\027" then self.model.ui:finishTool() return true else return false end end ---------------------------------------------------------------------- INKTOOL = {} INKTOOL.__index = INKTOOL function INKTOOL:new(model) local tool = {} setmetatable(tool, INKTOOL) tool.model = model local v = model.ui:pos() tool.v = { v } model.ui:shapeTool(tool) local s = model.doc:sheets():find("color", model.attributes.stroke) tool.setColor(s.r, s.g, s.b) tool.w = model.doc:sheets():find("pen", model.attributes.pen) model.ui:setCursor(tool.w, s.r, s.g, s.b) return tool end function INKTOOL:compute() self.shape = { type="curve", closed=false } for i = 2, #self.v do self.shape[#self.shape + 1] = { type="segment", self.v[i-1], self.v[i] } end self.setShape( { self.shape }, 0, self.w * self.model.ui:zoom()) end function INKTOOL:mouseButton(button, modifiers, press) self.model.ui:finishTool() if self.shape then local obj = ipe.Path(self.model.attributes, { self.shape }) -- round linecaps are prettier for handwriting obj:set("linecap", "round") self.model:creation("create ink path", obj) else -- mouse was pressed and released without movement local shape = { type="curve", closed=false, { type="segment", self.v[1], self.v[1] } } local obj = ipe.Path(self.model.attributes, { shape }) -- must make round linecap, otherwise it will be invisible obj:set("linecap", "round") self.model:creation("create ink dot", obj) end end function INKTOOL:mouseMove() self.v[#self.v + 1] = self.model.ui:pos() self:compute() self.model.ui:update(false) -- update tool end function INKTOOL:key(code, modifiers, text) if text == "\027" then self.model.ui:finishTool() return true else return false end end ---------------------------------------------------------------------- function MODEL:shredObject() local bound = prefs.close_distance local pos = self.ui:unsnappedPos() local p = self:page() local closest for i,obj,sel,layer in p:objects() do if p:visible(self.vno, i) and not p:isLocked(layer) then local d = p:distance(i, pos, bound) if d < bound then closest = i; bound = d end end end if closest then local t = { label="shred object", pno = self.pno, vno = self.vno, num = closest, original=self:page():clone(), undo=revertOriginal, } t.redo = function (t, doc) local p = doc[t.pno] p:remove(t.num) p:ensurePrimarySelection() end self:register(t) else self.ui:explain("No object found to shred") end end ---------------------------------------------------------------------- function MODEL:createMark() local obj = ipe.Reference(self.attributes, self.attributes.markshape, self.ui:pos()) self:creation("create mark", obj) end ---------------------------------------------------------------------- function MODEL:createText(mode) local prompt local pos = self.ui:pos() if mode == "math" then prompt = "Enter Latex source for math formula" else prompt = "Enter Latex source" end local d = ipeui.Dialog(self.ui:win(), "Create text object") d:add("label", "label", { label=prompt }, 1, 1) d:add("text", "text", { syntax="latex" }, 2, 1) addEditorField(d, "text") d:addButton("cancel", "&Cancel", "reject") d:addButton("ok", "&Ok", "accept") d:setStretch("row", 2, 1) d:set("ignore-cancel", true) if prefs.auto_external_editor then externalEditor(d, "text") end local r = d:execute(prefs.editor_size) if r then local t = d:get("text") if mode == "math" then t = "$" .. t .. "$" end local obj = ipe.Text(self.attributes, t, pos) self:creation("create text", obj) self:autoRunLatex() end end ---------------------------------------------------------------------- function MODEL:createParagraph(pos, width, pinned) local styles = self.doc:sheets():allNames("textstyle") local sizes = self.doc:sheets():allNames("textsize") local d = ipeui.Dialog(self.ui:win(), "Create text object") d:add("label", "label", { label="Enter latex source" }, 1, 1) d:add("style", "combo", styles, 1, 3) d:add("size", "combo", sizes, 1, 4) d:add("text", "text", { syntax="latex" }, 2, 1, 1, 4) addEditorField(d, "text") d:addButton("cancel", "&Cancel", "reject") d:addButton("ok", "&Ok", "accept") d:setStretch("row", 2, 1) d:setStretch("column", 2, 1) d:set("ignore-cancel", true) local style = indexOf(self.attributes.textstyle, styles) if not style then style = indexOf("normal", styles) end local size = indexOf(self.attributes.textsize, sizes) if not size then size = indexOf("normal", sizes) end d:set("style", style) d:set("size", size) if prefs.auto_external_editor then externalEditor(d, "text") end local r = d:execute(prefs.editor_size) if r then local t = d:get("text") local style = styles[d:get("style")] local size = sizes[d:get("size")] local obj = ipe.Text(self.attributes, t, pos, width) obj:set("textsize", size) obj:set("textstyle", style) if pinned then obj:set("pinned", "horizontal") end self:creation("create text paragraph", obj) self:autoRunLatex() end end function MODEL:action_insert_text_box() local r = self:page():textBox(self.doc:sheets()) self:createParagraph(r:topLeft(), r:width(), true) end ---------------------------------------------------------------------- PARAGRAPHTOOL = {} PARAGRAPHTOOL.__index = PARAGRAPHTOOL function PARAGRAPHTOOL:new(model) local tool = {} setmetatable(tool, PARAGRAPHTOOL) tool.model = model local v = model.ui:pos() tool.v = { v, v } model.ui:shapeTool(tool) tool.setColor(1.0, 0, 1.0) return tool end function PARAGRAPHTOOL:compute() self.v[2] = V(self.model.ui:pos().x, self.v[1].y - 20) self.shape = boxshape(self.v[1], self.v[2]) end function PARAGRAPHTOOL:mouseButton(button, modifiers, press) if not press then return end self:compute() self.model.ui:finishTool() local pos = V(math.min(self.v[1].x, self.v[2].x), self.v[1].y) local wid = math.abs(self.v[2].x - self.v[1].x) self.model:createParagraph(pos, wid) end function PARAGRAPHTOOL:mouseMove() self:compute() self.setShape( { self.shape } ) self.model.ui:update(false) -- update tool end function PARAGRAPHTOOL:key(code, modifiers, text) if text == "\027" then self.model.ui:finishTool() return true else return false end end ---------------------------------------------------------------------- CHANGEWIDTHTOOL = {} CHANGEWIDTHTOOL.__index = CHANGEWIDTHTOOL function CHANGEWIDTHTOOL:new(model, prim, obj) local tool = {} setmetatable(tool, CHANGEWIDTHTOOL) tool.model = model tool.prim = prim tool.obj = obj tool.pos = obj:matrix() * obj:position() tool.wid = obj:get("width") model.ui:shapeTool(tool) tool.setColor(1.0, 0, 1.0) tool.setShape( { boxshape(tool.pos, tool.pos + V(tool.wid, -20)) } ) model.ui:update(false) -- update tool return tool end function CHANGEWIDTHTOOL:compute() local w = self.model.ui:pos() self.nwid = self.wid + (w.x - self.v.x) self.shape = boxshape(self.pos, self.pos + V(self.nwid, -20)) end function CHANGEWIDTHTOOL:mouseButton(button, modifiers, press) if press then if not self.v then self.v = self.model.ui:pos() end else self:compute() self.model.ui:finishTool() self.model:setAttributeOfPrimary(self.prim, "width", self.nwid) self.model:autoRunLatex() end end function CHANGEWIDTHTOOL:mouseMove() if self.v then self:compute() self.setShape( { self.shape } ) self.model.ui:update(false) -- update tool end end function CHANGEWIDTHTOOL:key(code, modifiers, text) if text == "\027" then self.model.ui:finishTool() return true else return false end end function MODEL:action_change_width() local p = self:page() local prim = p:primarySelection() if not prim or p[prim]:type() ~= "text" or not p[prim]:get("minipage") then self.ui:explain("no selection or not a minipage object") return end CHANGEWIDTHTOOL:new(self, prim, p[prim]) end ---------------------------------------------------------------------- function MODEL:startTransform(mode, withShift) self:updateCloseSelection(false) if mode == "stretch" and withShift then mode = "scale" end self.ui:transformTool(self:page(), self.vno, mode, withShift, function (m) self:transformation(mode, m) end) end function MODEL:startModeTool(modifiers) if self.mode == "select" then self.ui:selectTool(self:page(), self.vno, prefs.select_distance, modifiers.shift) elseif (self.mode == "translate" or self.mode == "stretch" or self.mode == "rotate") then self:startTransform(self.mode, modifiers.shift) elseif self.mode == "pan" then self.ui:panTool(self:page(), self.vno) elseif self.mode == "shredder" then self:shredObject() elseif self.mode == "rectangles" then BOXTOOL:new(self, modifiers.shift) elseif self.mode == "splinegons" then SPLINEGONTOOL:new(self) elseif (self.mode == "lines" or self.mode == "polygons" or self.mode == "splines") then LINESTOOL:new(self, self.mode) elseif self.mode:sub(1,6) == "circle" then CIRCLETOOL:new(self, self.mode) elseif self.mode:sub(1,3) == "arc" then ARCTOOL:new(self, self.mode) elseif self.mode == "ink" then INKTOOL:new(self) elseif self.mode == "marks" then self:createMark() elseif self.mode == "label" or self.mode == "math" then self:createText(self.mode) elseif self.mode == "paragraph" then PARAGRAPHTOOL:new(self) else print("start mode tool:", self.mode) end end local mouse_mappings = { select = function (m, mo) m.ui:selectTool(m:page(), m.vno, prefs.select_distance, mo.shift) end, translate = function (m, mo) m:startTransform("translate", mo.shift) end, rotate = function (m, mo) m:startTransform("rotate", mo.shift) end, stretch = function (m, mo) m:startTransform("stretch", mo.shift) end, scale = function (m, mo) m:startTransform("stretch", true) end, pan = function (m, mo) m.ui:panTool(m:page(), m.vno) end, menu = function (m, mo) m:propertiesPopup() end, shredder = function (m, mo) m:shredObject() end, } function MODEL:mouseButtonAction(button, modifiers) -- print("Mouse button", button, modifiers.alt, modifiers.control) if button == 1 and not modifiers.alt and not modifiers.control and not modifiers.meta then self:startModeTool(modifiers) else local s = "" if button == 1 then s = "left" elseif button == 2 then s = "right" elseif button == 4 then s = "middle" elseif button == 8 then s = "button8" elseif button == 16 then s = "button9" elseif button == 0 then -- This is a hack because of the Qt limitation. -- It really means any other button. s = "button10" end if modifiers.shift then s = s .. "_shift" end if modifiers.control then s = s .. "_control" end if modifiers.alt then s = s .. "_alt" end if modifiers.meta then s = s .. "_meta" end local r = mouse[s] if type(r) == "string" then r = mouse_mappings[r] end if r then r(self, modifiers) else print("No mouse action defined for " .. s) end end end ---------------------------------------------------------------------- function apply_text_edit(d, data, run_latex) -- refuse to do anything with empty text if string.match(d:get("text"), "^%s*$") then return end local model = data.model local final = data.obj:clone() final:setText(d:get("text")) if data.style then final:set("textstyle", data.styles[d:get("style")]) end if data.size then final:set("textsize", data.sizes[d:get("size")]) end local t = { label="edit text", pno=model.pno, vno=model.vno, original=data.obj:clone(), primary=data.prim, final=final, } t.undo = function (t, doc) doc[t.pno]:replace(t.primary, t.original) end t.redo = function (t, doc) doc[t.pno]:replace(t.primary, t.final) end model:register(t) -- need to update data.obj for the next run! data.obj = final if run_latex then model:runLatex() end end function MODEL:action_edit_text(prim, obj) local mp = obj:get("minipage") local d = ipeui.Dialog(self.ui:win(), "Edit text object") local data = { model=self, styles = self.doc:sheets():allNames("textstyle"), sizes = self.doc:sheets():allNames("textsize"), prim=prim, obj=obj, } d:add("label", "label", { label="Edit latex source" }, 1, 1) d:add("text", "text", { syntax="latex" }, 2, 1, 1, 4) d:addButton("apply", "&Apply", function (d) apply_text_edit(d, data, true) end) addEditorField(d, "text") d:addButton("cancel", "&Cancel", "reject") d:addButton("ok", "&Ok", "accept") d:setStretch("row", 2, 1) d:setStretch("column", 2, 1) d:set("text", obj:text()) d:set("ignore-cancel", true) local style = nil local size = nil if mp then data.style = indexOf(obj:get("textstyle"), data.styles) if data.style then d:add("style", "combo", data.styles, 1, 3) d:set("style", data.style) end data.size = indexOf(obj:get("textsize"), data.sizes) if data.size then d:add("size", "combo", data.sizes, 1, 4) d:set("size", data.size) end end if prefs.auto_external_editor then externalEditor(d, "text") end local r = d:execute(prefs.editor_size) if not r or string.match(d:get("text"), "^%s*$") then return end apply_text_edit(d, data, self.auto_latex) end function MODEL:action_edit() local p = self:page() local prim = p:primarySelection() if not prim then self.ui:explain("no selection") return end local obj = p[prim] if obj:type() == "text" then self:action_edit_text(prim, obj) elseif obj:type() == "path" then self:action_edit_path(prim, obj) else self:warning("Cannot edit " .. obj:type() .. " object", "Only text objects and path objects can be edited") end end ---------------------------------------------------------------------- PASTETOOL = {} PASTETOOL.__index = PASTETOOL function PASTETOOL:new(model, elements, pos) local tool = {} _G.setmetatable(tool, PASTETOOL) tool.model = model tool.elements = elements tool.start = model.ui:pos() if pos then tool.start = pos end local obj = ipe.Group(elements) tool.pinned = obj:get("pinned") model.ui:pasteTool(obj, tool) tool.setColor(1.0, 0, 0) tool:computeTranslation() tool.setMatrix(ipe.Translation(tool.translation)) return tool end function PASTETOOL:computeTranslation() self.translation = self.model.ui:pos() - self.start if self.pinned == "horizontal" or self.pinned == "fixed" then self.translation = V(0, self.translation.y) end if self.pinned == "vertical" or self.pinned == "fixed" then self.translation = V(self.translation.x, 0) end end function PASTETOOL:mouseButton(button, modifiers, press) self:computeTranslation() self.model.ui:finishTool() local t = { label="paste objects at cursor", pno = self.model.pno, vno = self.model.vno, elements = self.elements, layer = self.model:page():active(self.model.vno), translation = ipe.Translation(self.translation), } t.undo = function (t, doc) local p = doc[t.pno] for i = 1,#t.elements do p:remove(#p) end end t.redo = function (t, doc) local p = doc[t.pno] for i,obj in ipairs(t.elements) do p:insert(nil, obj, 2, t.layer) p:transform(#p, t.translation) end p:ensurePrimarySelection() end self.model:page():deselectAll() self.model:register(t) end function PASTETOOL:mouseMove() self:computeTranslation() self.setMatrix(ipe.Translation(self.translation)) self.model.ui:update(false) -- update tool end function PASTETOOL:key(code, modifiers, text) if text == "\027" then self.model.ui:finishTool() return true else return false end end function MODEL:action_paste_at_cursor() local data = ipeui.clipboard() if data:sub(1,13) ~= " 1 then local targets = {} local i0 = indexOf(layer,layers) if i0 ~= 1 then targets[1] = "_top_" end for i,l in ipairs(layers) do if i ~= i0 - 1 and i ~= i0 then targets[#targets + 1] = l end end m:add("move", "Move " .. layer, targets, function (i, l) if l == "_top_" then return "to top" else return "after " .. l end end) end local r, no, subitem = m:execute(v.x, v.y) if r then self:layerAction(r, layer, subitem) end end ---------------------------------------------------------------------- function MODEL:layeraction_checkfrom(layer, arg) local p = self:page() local t = { label="make layer " .. layer .. " visible from view " .. self.vno, pno=self.pno, vno=self.vno, original=p:clone(), layer=layer, undo=revertOriginal } t.redo = function (t, doc) for j = t.vno, doc[t.pno]:countViews() do doc[t.pno]:setVisible(j, t.layer, true) end end self:register(t) end function MODEL:layeraction_select(layer, arg) local p = self:page() local t = { label="set visibility of layer " .. layer, pno=self.pno, vno=self.vno, layer=layer, original=p:visible(self.vno, layer), visible=arg, } t.undo = function (t, doc) doc[t.pno]:setVisible(t.vno, t.layer, t.original) end t.redo = function (t, doc) doc[t.pno]:setVisible(t.vno, t.layer, t.visible) end self:register(t) self:deselectNotInView() end function MODEL:layeraction_lock(layer, arg) local p = self:page() for j = 1, p:countViews() do if layer == p:active(j) then self:warning("Cannot lock layer '" .. layer .. "'.", "Layer '" .. layer .. "' is the active layer of view " .. j .. ".") return end end local t = { label="set locking of layer " .. layer, pno=self.pno, vno=self.vno, layer=layer, original=p:isLocked(layer), locked=arg, } t.undo = function (t, doc) doc[t.pno]:setLocked(t.layer, t.original) end t.redo = function (t, doc) doc[t.pno]:setLocked(t.layer, t.locked) end self:register(t) self:deselectNotInView() self:setPage() end function MODEL:layeraction_snap(layer, arg) local p = self:page() local t = { label="set snapping in layer " .. layer, pno=self.pno, vno=self.vno, layer=layer, original=p:hasSnapping(layer), snapping=arg, } t.undo = function (t, doc) doc[t.pno]:setSnapping(t.layer, t.original) end t.redo = function (t, doc) doc[t.pno]:setSnapping(t.layer, t.snapping) end self:register(t) end function MODEL:layeraction_move(layer, arg) local p = self:page() local target = 1 local current = indexOf(layer, p:layers()) if arg ~= "_top_" then target = indexOf(arg, p:layers()) if target < current then target = target + 1 end end local t = { label="move layer " .. layer, pno=self.pno, vno=self.vno, original=p:clone(), layer=layer, target=target, undo=revertOriginal } t.redo = function (t, doc) doc[t.pno]:moveLayer(t.layer, t.target) end self:register(t) end function MODEL:layeraction_active(layer) local p = self:page() if p:isLocked(layer) then self:warning("Cannot change active layer", "A locked layer cannot be the active layer") return end local t = { label="select active layer " .. layer, pno=self.pno, vno=self.vno, original=p:active(self.vno), final=layer, } t.undo = function (t, doc) doc[t.pno]:setActive(t.vno, t.original) end t.redo = function (t, doc) doc[t.pno]:setActive(t.vno, t.final) end self:register(t) end function MODEL:layeraction_rename(layer) local p = self:page() local name = self:getString("Enter new name for layer '" .. layer .. "'") if not name then return end name = string.gsub(name, "%s+", "_") if indexOf(name, p:layers()) then self:warning("Cannot rename layer '" .. layer .. "'.", "The name '" .. name .. "' is already in use.") return end local t = { label="rename layer " .. layer .. " to " .. name, pno=self.pno, vno=self.vno, original=layer, final=name, } t.undo = function (t, doc) doc[t.pno]:renameLayer(t.final, t.original) for i = 1,p:countViews() do if p:active(i) == t.final then p:setActive(i, t.original) end end end t.redo = function (t, doc) doc[t.pno]:renameLayer(t.original, t.final) for i = 1,p:countViews() do if p:active(i) == t.original then p:setActive(i, t.final) end end end self:register(t) end function MODEL:layeraction_delete(layer) local p = self:page() for j = 1, p:countViews() do if layer == p:active(j) then self:warning("Cannot delete layer '" .. layer .. "'.", "Layer '" .. layer .. "' is the active layer of view " .. j .. ".") return end end local t = { label="delete layer " .. layer, pno=self.pno, vno=self.vno, original=p:clone(), layer=layer, undo=revertOriginal } t.redo = function (t, doc) local p = doc[t.pno] for i = #p,1,-1 do if p:layerOf(i) == t.layer then p:remove(i) end end p:removeLayer(t.layer) end self:register(t) end function MODEL:layeraction_merge(layer) local p = self:page() local active = p:active(self.vno) for j = 1, p:countViews() do if layer == p:active(j) then self:warning("Cannot remove layer '" .. layer .. "'.", "Layer '" .. layer .. "' is the active layer of view " .. j .. ".") return end end local t = { label="merge layer " .. layer .. " into " .. active, pno=self.pno, vno=self.vno, original=p:clone(), layer=layer, target=active, undo=revertOriginal } t.redo = function (t, doc) local p = doc[t.pno] for i = 1,#p do if p:layerOf(i) == t.layer then p:setLayerOf(i, t.target) end end p:removeLayer(t.layer) end self:register(t) end ---------------------------------------------------------------------- function MODEL:action_ipelet(a) local i = a:find("_",8) local method = tonumber(a:sub(8,i-1)) local name = a:sub(i+1) for _, ipelet in ipairs(ipelets) do if ipelet.name == name then if (ipelet.methods and ipelet.methods[method] and ipelet.methods[method].run) then ipelet.methods[method].run(self, method) else ipelet.run(self, method) end break end end self.ui:update() end ---------------------------------------------------------------------- function MODEL:action_new_window() MODEL:new() end function MODEL:action_run_latex() self:runLatex() end function MODEL:action_close() self.ui:close() end function MODEL:action_quit() ipeui.closeAllWindows() end function MODEL:action_auto_latex() self.auto_latex = self.ui:actionState("auto_latex") print("Auto is", self.auto_latex) end ---------------------------------------------------------------------- function MODEL:action_new() if not self:checkModified() then return end self:newDocument() end function MODEL:action_open() if not self:checkModified() then return end local s, f = ipeui.fileDialog(self.ui:win(), "open", "Open file", "Ipe files (*.ipe *.pdf *.eps *.xml);;All files (*.*)") if s then self:loadDocument(s) else self.ui:explain("Loading canceled") end end function MODEL:action_save() if not self.file_name then return self:action_save_as() else return self:saveDocument() end end function MODEL:action_save_as() local dir if self.file_name then dir = self.file_name:match("^(.+)/[^/]+") end if not dir then dir = prefs.save_as_directory end local s, f = ipeui.fileDialog(self.ui:win(), "save", "Save file as", "XML (*.ipe *.xml);;PDF (*.pdf);;EPS (*.eps)", dir, self.dialog_filter) local fmap = { XML=".ipe", PDF=".pdf", EPS=".eps" } if s then self.dialog_filter = f if not formatFromFileName(s) then s = s .. fmap[f:sub(1,3)] end if ipe.fileExists(s) then local b = ipeui.messageBox(self.ui:win(), "question", "File already exists!", "Do you wish to overwrite?
    " .. s, "okcancel") if b ~= 1 then self.ui:explain("File not saved") return end end return self:saveDocument(s) end end ---------------------------------------------------------------------- function MODEL:action_manual() local url = "file:///" .. config.docdir .. "/manual.html" if ipeui.startBrowser then ipeui.startBrowser(url) else os.execute(prefs.browser:format(url)) end end function MODEL:action_show_configuration() local s = "" s = s .. " * Lua code: " .. package.path s = s .. "\n * Style directories:\n - " .. table.concat(config.styleDirs, "\n - ") s = s .. "\n * Styles for new documents: " .. table.concat(prefs.styles, ", ") s = s .. "\n * Autosave file: " .. prefs.autosave_filename s = s .. "\n * Documentation: " .. config.docdir s = s .. "\n * Ipelets:\n - " .. table.concat(config.ipeletDirs, "\n - ") s = s .. "\n * Latex directory: " .. config.latexdir s = s .. "\n * Fontmap: " .. config.fontmap s = s .. "\n * Icons: " .. config.icons ipeui.messageBox(self.ui:win(), "information", "Ipe configuration", s) end function MODEL:action_about_ipelets() local s = "" for _,v in ipairs(ipelets) do s = s .. " * " .. v.label .. "\n " .. v.about .. "\n" end ipeui.messageBox(self.ui:win(), "information", "About the ipelets", s) end function MODEL:action_keyboard() local s = prefs.keyboard if s then os.execute(s) else self:warning("No onscreen keyboard defined.", "Edit preferences to define an onscreen keyboard.") end end ---------------------------------------------------------------------- function MODEL:action_set_origin_snap() self.snap.origin = self.ui:simpleSnapPos() self.snap.snapangle = true self.snap.with_axes = true self.ui:setActionState("snapangle", true) self.ui:setSnap(self.snap) self.ui:setFifiVisible(true) self.ui:update() end function MODEL:action_hide_axes() self.snap.with_axes = false self.snap.snapangle = false self.ui:setActionState("snapangle", false) self.ui:setSnap(self.snap) self.ui:update() end function MODEL:action_set_direction() self.snap.with_axes = true; self.snap.orientation = (self.ui:simpleSnapPos() - self.snap.origin):angle() self.ui:setSnap(self.snap) self.ui:update() end function MODEL:action_reset_direction() self.snap.orientation = 0 self.ui:setSnap(self.snap) self.ui:update() end function MODEL:setLine() local origin, dir = self:page():findEdge(self.ui:simpleSnapPos()) if not origin then self.ui:explain("Mouse is not on an edge") return false else self.snap.with_axes = true; self.snap.orientation = dir self.snap.origin = origin self.ui:update() return true end end function MODEL:action_set_line() if self:setLine() then self.ui:setSnap(self.snap) end end function MODEL:action_set_line_snap() if self:setLine() then self.snap.snapangle = true self.ui:setFifiVisible(true) self.ui:setActionState("snapangle", true) self.ui:setSnap(self.snap) end end ---------------------------------------------------------------------- function MODEL:action_select_all() local p = self:page() for i,obj,sel,layer in p:objects() do if not sel and p:visible(self.vno, i) and not p:isLocked(layer) then self:page():setSelect(i, 2) end end p:ensurePrimarySelection() self.ui:update(false) end function MODEL:action_select_in_active_layer() local p = self:page() local active = p:active(self.vno) p:deselectAll() for i,obj,sel,layer in p:objects() do if layer == active then self:page():setSelect(i, 2) end end p:ensurePrimarySelection() self.ui:update(false) end function MODEL:action_select_in_layer(lay) local p = self:page() p:deselectAll() for i,obj,sel,layer in p:objects() do if layer == lay then self:page():setSelect(i, 2) end end p:ensurePrimarySelection() self.ui:update(false) end function MODEL:saction_move_to_active_layer() local p = self:page() local active = p:active(self.vno) local t = { label="move to layer " .. active, pno = self.pno, vno = self.vno, selection=self:selection(), original=p:clone(), active=active, undo=revertOriginal, } t.redo = function (t, doc) local p = doc[t.pno] for _,i in ipairs(t.selection) do p:setLayerOf(i, t.active) end end self:register(t) end function MODEL:action_move_to_layer(lay) local p = self:page() if not p:hasSelection() then self.ui:explain("no selection") return end local t = { label="move to layer " .. lay, pno = self.pno, vno = self.vno, selection=self:selection(), original=p:clone(), layer=lay, undo=revertOriginal, } t.redo = function (t, doc) local p = doc[t.pno] for _,i in ipairs(t.selection) do p:setLayerOf(i, t.layer) end end self:register(t) end ---------------------------------------------------------------------- function MODEL:action_grid_visible() self.snap.grid_visible = self.ui:actionState("grid_visible"); self.ui:setSnap(self.snap) self.ui:update() end function MODEL:action_zoom_in() local nzoom = prefs.zoom_factor * self.ui:zoom() if nzoom > prefs.max_zoom then nzoom = prefs.max_zoom end self.ui:setZoom(nzoom) self.ui:update() end function MODEL:action_zoom_out() local nzoom = self.ui:zoom() / prefs.zoom_factor if nzoom < prefs.min_zoom then nzoom = prefs.min_zoom end self.ui:setZoom(nzoom) self.ui:update() end function MODEL:wheel_zoom(delta) local origin = self.ui:unsnappedPos() local zoom = self.ui:zoom() local offset = zoom * (self.ui:pan() - origin) local nzoom if delta > 0 then nzoom = prefs.wheel_zoom_factor * zoom else nzoom = zoom / prefs.wheel_zoom_factor end if nzoom > prefs.max_zoom then nzoom = prefs.max_zoom end if nzoom < prefs.min_zoom then nzoom = prefs.min_zoom end self.ui:setZoom(nzoom) self.ui:setPan(origin + (1/nzoom) * offset) self.ui:update() end function MODEL:action_wheel_zoom_out() self:wheel_zoom(-1) end function MODEL:action_wheel_zoom_in() self:wheel_zoom(1) end -- Change resolution to 72 dpi and maximize interesting visible area. -- As suggested by Rene: -- 1) scale to the proper size, with the center of the canvas as the -- origin of the scaling. -- 2) If there is a horizontal and/or vertical translation that makes -- a larger part of the *bounding box* of the objects visible, then -- translate (and maximize the part of the bounding box that is -- visible). -- 3) If there is a horizontal and/or vertical translation that makes -- a larger part of the paper visible, then translate (and maximize -- the part of the paper that is visible), under the restriction -- that no part of the bounding box of the objects may be moved -- `out of sight' in this step. (Note that there may be objects -- outside the paper). local function adjustPan(cmin, cmax, omin, omax, pmin, pmax) local dx = 0; -- if objects stick out on both sides, there is nothing we can do if omin <= cmin and omax >= cmax then return dx end if omax > cmax and omin > cmin then -- we can see more objects if we shift canvas right dx = math.min(omin - cmin, omax - cmax) elseif omin < cmin and omax < cmax then -- we can see more objects if we shift canvas left dx = -math.min(cmin - omin, cmax - omax) end -- shift canvas cmin = cmin + dx cmax = cmax + dx -- if canvas fully contained in media, done if pmin <= cmin and pmax >= cmax then return dx end -- if media contained in canvas, can't improve if cmin < pmin and pmax < cmax then return dx end if pmin > cmin then -- improvement possible by shifting canvas right if omin > cmin then dx = dx + math.min(omin - cmin, pmin - cmin, pmax - cmax) end else -- improvement possible by shifting canvas left if omax < cmax then dx = dx - math.min(cmax - omax, cmax - pmax, cmin - pmin) end end return dx end function MODEL:action_normal_size() local p = self:page() self.ui:setZoom(1) local layout = self.doc:sheets():find("layout") local paper = ipe.Rect() paper:add(-layout.origin) paper:add(-layout.origin + layout.papersize) local bbox = ipe.Rect() for i = 1,#p do bbox:add(p:bbox(i)) end local canvas = ipe.Rect() canvas:add(self.ui:pan() - 0.5 * self.ui:canvasSize()) canvas:add(self.ui:pan() + 0.5 * self.ui:canvasSize()) local pan = V(adjustPan(canvas:left(), canvas:right(), bbox:left(), bbox:right(), paper:left(), paper:right()), adjustPan(canvas:bottom(), canvas:top(), bbox:bottom(), bbox:top(), paper:bottom(), paper:top())) self.ui:setPan(self.ui:pan() + pan) self.ui:update() end function MODEL:action_fit_page() local layout = self.doc:sheets():find("layout") local box = ipe.Rect() box:add(-layout.origin - V(2,2)) box:add(-layout.origin + layout.papersize + V(2,2)) self:fitBox(box); end function MODEL:action_fit_width() local layout = self.doc:sheets():find("layout") local box = ipe.Rect() local y0 = self.ui:pan().y box:add(V(-layout.origin.x - 2, y0 - 2)) box:add(V(-layout.origin.x + layout.papersize.x + 2, y0 + 2)) self:fitBox(box); end function MODEL:action_fit_top() self:action_fit_width() -- sets zoom and x-pan correctly local layout = self.doc:sheets():find("layout") local x0 = self.ui:pan().x local ht = 0.5 * self.ui:canvasSize().y / self.ui:zoom() local y0 = -layout.origin.y + layout.papersize.y + 2 - ht self.ui:setPan(V(x0, y0)) end function MODEL:action_fit_objects() local box = ipe.Rect() local m = ipe.Matrix() local p = self:page() for i,obj,_,layer in p:objects() do if p:visible(self.vno, i) then obj:addToBBox(box, m, false) end end self:fitBox(box); end function MODEL:saction_fit_selection() local box = ipe.Rect() local m = ipe.Matrix() local p = self:page() for i,obj,sel,_ in p:objects() do if sel then obj:addToBBox(box, m, false) end end self:fitBox(box); end function MODEL:action_pan_here() v = self.ui:unsnappedPos() self.ui:setPan(v) self.ui:update() end ---------------------------------------------------------------------- function MODEL:action_next_view() self:nextView(1) self:setPage() end function MODEL:action_previous_view() self:nextView(-1) self:setPage() end function MODEL:action_first_view() self.vno = 1 self:setPage() end function MODEL:action_last_view() self.vno = self:page():countViews() self:setPage() end function MODEL:action_new_view() local t = { label="new view", pno = self.pno, vno0 = self.vno, vno1 = self.vno + 1, } t.undo = function (t, doc) doc[t.pno]:removeView(t.vno1) end t.redo = function (t, doc) local p = doc[t.pno] p:insertView(t.vno1, p:active(t.vno0)) for i,layer in ipairs(p:layers()) do p:setVisible(t.vno1, layer, p:visible(t.vno0, layer)) end end self:register(t) self:nextView(1) self:setPage() end function MODEL:action_new_layer_view() local t = { label="new layer and view", pno = self.pno, vno0 = self.vno, vno1 = self.vno + 1, } t.undo = function (t, doc) doc[t.pno]:removeLayer(t.layer) doc[t.pno]:removeView(t.vno1) end t.redo = function (t, doc) local p = doc[t.pno] p:insertView(t.vno1, p:active(t.vno0)) for i,layer in ipairs(p:layers()) do p:setVisible(t.vno1, layer, p:visible(t.vno0, layer)) end t.layer = doc[t.pno]:addLayer() p:setVisible(t.vno1, t.layer, true) p:setActive(t.vno1, t.layer) end self:register(t) self:nextView(1) self:setPage() end function MODEL:action_delete_view() local p = self:page() if p:countViews() < 2 then self.ui:explain("cannot delete single view of a page") return end local t = { label="delete view", pno = self.pno, vno0 = self.vno, vno1 = self.vno, original = p:clone(), undo = revertOriginal, } if self.vno == p:countViews() then t.vno1 = self.vno - 1 end t.redo = function (t, doc) doc[t.pno]:removeView(t.vno0) end t.redo(t, self.doc) self.vno = t.vno1 self:registerOnly(t) self.ui:explain(t.label) end function MODEL:action_edit_effects() local p = self:page() local effect = p:effect(self.vno) local list = self.doc:sheets():allNames("effect") table.insert(list, 1, "normal") local d = ipeui.Dialog(self.ui:win(), "Edit view effect") local label = "Choose effect for view " .. self.vno d:add("label", "label", { label=label }, 1, 1) d:add("combo", "combo", list, 2, 1) d:addButton("cancel", "&Cancel", "reject") d:addButton("ok", "&Ok", "accept") d:set("combo", indexOf(effect, list)) if not d:execute() then return end local final = list[d:get("combo")] local t = { label="set effect of view " .. self.vno .. " to " .. final, pno = self.pno, vno = self.vno, original = effect, final = final, } t.undo = function (t, doc) p:setEffect(t.vno, t.original) end t.redo = function (t, doc) p:setEffect(t.vno, t.final) end self:register(t) end ---------------------------------------------------------------------- function MODEL:action_next_page() self:nextPage(1) self:setPage() end function MODEL:action_previous_page() self:nextPage(-1) self:setPage() end function MODEL:action_first_page() self.pno = 1 self.vno = 1 self:setPage() end function MODEL:action_last_page() self.pno = #self.doc self.vno = 1 self:setPage() end function MODEL:action_copy_page() local data = self:page():xml("ipepage") ipeui.setClipboard(data) self.ui:explain("page copied to clipboard") end function MODEL:action_cut_page() if #self.doc == 1 then self:warning("Cannot cut page", "This is the only page of the document.") return end local t = { label="cut page " .. self.pno, pno0 = self.pno, pno1 = self.pno, vno = 1, original = self:page():clone(), } if self.pno == #self.doc then t.pno1 = self.pno - 1 end t.undo = function (t, doc) doc:insert(t.pno0, t.original) end t.redo = function (t, doc) doc:remove(t.pno0) end t.redo(t, self.doc) self.pno = t.pno1 self.vno = 1 self:registerOnly(t) self.ui:explain(t.label .. " and copied to clipboard") local data = t.original:xml("ipepage") ipeui.setClipboard(data) end function MODEL:action_new_page() local t = { label="new page", pno0 = self.pno, pno1 = self.pno + 1, vno0 = self.vno, vno1 = 1, } t.undo = function (t, doc) doc:remove(t.pno1) end t.redo = function (t, doc) doc:insert(t.pno1, ipe.Page()) end self:register(t) self:nextPage(1) self:setPage() end function MODEL:action_paste_page() local data = ipeui.clipboard() if data:sub(1,9) ~= "" then self:warning("No Ipe page to paste") return end local p = ipe.Page(data) if not p then self:warning("Could not parse Ipe page on clipboard") return end local t = { label="paste page", pno0 = self.pno, pno1 = self.pno + 1, vno0 = self.vno, vno1 = 1, page = p, } t.undo = function (t, doc) doc:remove(t.pno1) end t.redo = function (t, doc) doc:insert(t.pno1, t.page) end self:register(t) self:nextPage(1) self:setPage() end function MODEL:action_delete_page() if #self.doc == 1 then self:warning("Cannot delete page", "This is the only page of the document.") return end local t = { label="delete page " .. self.pno, pno0 = self.pno, pno1 = self.pno, vno = 1, original = self:page():clone(), } if self.pno == #self.doc then t.pno1 = self.pno - 1 end t.undo = function (t, doc) doc:insert(t.pno0, t.original) end t.redo = function (t, doc) doc:remove(t.pno0) end t.redo(t, self.doc) self.pno = t.pno1 self.vno = 1 self:registerOnly(t) self.ui:explain(t.label) end local function update_dialog(d, sec) local on = d:get("t" .. sec) d:setEnabled(sec, not on) if on then d:set(sec, "") end end function MODEL:action_edit_title() local d = ipeui.Dialog(self.ui:win(), "Ipe: Edit page title and sections") d:add("label1", "label", { label="Page title"}, 1, 1, 1, 4) d:add("title", "text", {}, 2, 1, 1, 4) d:add("label2", "label", { label="Sections"}, 3, 1, 1, 4) d:add("label3", "label", { label="Section:" }, 4, 1) d:add("tsection", "checkbox", { label="Use &title", action=function (d) update_dialog(d, "section") end } , 4, 2) d:add("section", "input", {}, 5, 2, 1, 3) d:add("label4", "label", { label="Subsection:" }, 6, 1) d:add("tsubsection", "checkbox", { label="Use titl&e", action=function (d) update_dialog(d, "subsection") end } , 6, 2) d:add("subsection", "input", {}, 7, 2, 1, 3) d:addButton("cancel", "&Cancel", "reject") d:addButton("ok", "&Ok", "accept") d:setStretch("row", 2, 1) d:setStretch("column", 2, 1) -- setup original values local ti = self:page():titles() d:set("title", ti.title) if ti.section then d:set("section", ti.section) else d:set("tsection", true) d:setEnabled("section", false) end if ti.subsection then d:set("subsection", ti.subsection) else d:set("tsubsection", true) d:setEnabled("subsection", false) end if not d:execute() then return end local final = { title = d:get("title") } if not d:get("tsection") then final.section = d:get("section") end if not d:get("tsubsection") then final.subsection = d:get("subsection") end if prefs.automatic_use_title and ti.title ~= final.title then final.section = true final.tsection = true end local t = { label="change title and sections of page " .. self.pno, pno = self.pno, vno = self.vno, original = ti, final = final, } t.undo = function (t, doc) doc[t.pno]:setTitles(t.original) end t.redo = function (t, doc) doc[t.pno]:setTitles(t.final) end self:register(t) end function MODEL:action_edit_notes() local d = ipeui.Dialog(self.ui:win(), "Ipe: Edit page notes") d:add("label1", "label", { label="Page notes"}, 1, 1) d:add("notes", "text", {}, 2, 1) d:addButton("cancel", "&Cancel", "reject") d:addButton("ok", "&Ok", "accept") d:setStretch("row", 2, 1) -- setup original values local n = self:page():notes() d:set("notes", n) if not d:execute() then return end local final = d:get("notes") if string.match(final, "^%s*$") then final = "" end local t = { label="change notes on page " .. self.pno, pno = self.pno, vno = self.vno, original = n, final = final, } t.undo = function (t, doc) doc[t.pno]:setNotes(t.original) end t.redo = function (t, doc) doc[t.pno]:setNotes(t.final) end self:register(t) end -- rearrange pages of document -- new order is given by arr -- 0 entries in arr are taken from newpages -- returns list of pages that remained unused function arrange_pages(doc, arr, newpages) -- take all pages from document local pg = {} while #doc > 0 do pg[#pg+1] = doc:remove(1) end -- insert pages again in new order for i = 1,#arr do local no = arr[i] if no > 0 then doc:append(pg[no]) -- clones the page pg[no] = nil -- mark as used else doc:append(table.remove(newpages, 1)) end end -- return unused pages local unused = {} for i = 1,#pg do if pg[i] then unused[#unused+1] = pg[i] end end return unused end function MODEL:action_page_sorter() local arr = self.ui:pageSorter(self.doc) if not arr then return end -- canceled if #arr == 0 then self:warning("You cannot delete all pages of the document") return end -- compute reverse 'permutation' local rev = {} for i = 1,#self.doc do rev[i] = 0 end for i = 1,#arr do rev[arr[i]] = i end local t = { label="rearrangement of pages", pno = 1, vno = 1, arr = arr, rev = rev, } t.undo = function (t, doc) arrange_pages(doc, t.rev, t.deleted) end t.redo = function (t, doc) t.deleted = arrange_pages(doc, t.arr, {}) end self:register(t) end ---------------------------------------------------------------------- function MODEL:action_new_layer() local t = { label="new layer", pno = self.pno, vno = self.vno, } t.redo = function (t, doc) t.layer = doc[t.pno]:addLayer() end t.undo = function (t, doc) doc[t.pno]:removeLayer(t.layer) end self:register(t) end function MODEL:action_rename_active_layer() local p = self:page() local active = p:active(self.vno) self:layeraction_rename(active) end ---------------------------------------------------------------------- function MODEL:saction_delete() local t = { label="delete", pno = self.pno, vno = self.vno, selection=self:selection(), original=self:page():clone(), undo=revertOriginal, } t.redo = function (t, doc) local p = doc[t.pno] for i = #t.selection,1,-1 do p:remove(t.selection[i]) end end self:register(t) end function MODEL:saction_edit_as_xml() local prim = self:page():primarySelection() local xml = self:page()[prim]:xml() local d = ipeui.Dialog(self.ui:win(), "Edit as XML") d:add("xml", "text", { syntax="xml" }, 1, 1) addEditorField(d, "xml") d:addButton("cancel", "&Cancel", "reject") d:addButton("ok", "&Ok", "accept") d:setStretch("row", 1, 1); d:set("xml", xml) if not d:execute() then return end local obj = ipe.Object(d:get("xml")) if not obj then self:warning("Cannot parse XML") return end local t = { label="edit object in XML", pno = self.pno, vno = self.vno, primary = prim, original = self:page()[prim]:clone(), final = obj, } t.undo = function (t, doc) doc[t.pno]:replace(t.primary, t.original) end t.redo = function (t, doc) doc[t.pno]:replace(t.primary, t.final) end self:register(t) end ---------------------------------------------------------------------- function MODEL:saction_group() local p = self:page() local selection = self:selection() local elements = {} for _,i in ipairs(selection) do elements[#elements + 1] = p[i]:clone() end local final = ipe.Group(elements) p:deselectAll() local t = { label="group", pno = self.pno, vno = self.vno, original = p:clone(), selection = selection, layer = p:active(self.vno), final = final, undo = revertOriginal, } t.redo = function (t, doc) local p = doc[t.pno] for i = #t.selection,1,-1 do p:remove(t.selection[i]) end p:insert(nil, t.final, 1, t.layer) end self:register(t) end -- does not pass pinning and allowed transformation to elements function MODEL:saction_ungroup() local p = self:page() local prim = p:primarySelection() if p[prim]:type() ~= "group" then self.ui:explain("primary selection is not a group") return end p:deselectAll() local t = { label="ungroup", pno = self.pno, vno = self.vno, original = p[prim]:clone(), primary = prim, originalLayer = p:layerOf(prim), layer = p:active(self.vno), elements = p[prim]:elements(), matrix = p[prim]:matrix(), } t.undo = function (t, doc) local p = doc[t.pno] for i = 1,#t.elements do p:remove(#p) end p:insert(t.primary, t.original, nil, t.originalLayer) end t.redo = function (t, doc) local p = doc[t.pno] p:remove(t.primary) for _,obj in ipairs(t.elements) do p:insert(nil, obj, 2, t.layer) p:transform(#p, t.matrix) end p:ensurePrimarySelection() end self:register(t) end function MODEL:saction_front() local p = self:page() local selection = self:selection() local t = { label="front", pno = self.pno, vno = self.vno, original = p:clone(), selection = selection, primary = indexOf(p:primarySelection(), selection), undo = revertOriginal, } p:deselectAll() t.redo = function (t, doc) local p = doc[t.pno] local r,l = extractElements(p, t.selection) for i,obj in ipairs(r) do p:insert(nil, obj, (i == t.primary) and 1 or 2, l[i]) end end self:register(t) end function MODEL:saction_back() local p = self:page() local selection = self:selection() local t = { label="back", pno = self.pno, vno = self.vno, original = p:clone(), selection = selection, primary = indexOf(p:primarySelection(), selection), undo = revertOriginal, } p:deselectAll() t.redo = function (t, doc) local p = doc[t.pno] local r,l = extractElements(p, t.selection) for i,obj in ipairs(r) do p:insert(i, obj, (i == t.primary) and 1 or 2, l[i]) end end self:register(t) end function MODEL:saction_duplicate() local p = self:page() local t = { label="duplicate", pno = self.pno, vno = self.vno, selection = self:selection(), primary = self:page():primarySelection(), layer = self:page():active(self.vno), } t.undo = function (t, doc) local p = doc[t.pno] for i = 1,#t.selection do p:remove(#p) end end t.redo = function (t, doc) local p = doc[t.pno] for _,i in ipairs(t.selection) do p:insert(nil, p[i]:clone(), 2, t.layer) p:setSelect(i, nil) if i == t.primary then p:setSelect(#p, 1) end end end self:register(t) end local function moveTargetToSource (t, doc) local p = doc[t.pno] local target = (t.target > t.source) and (t.target - 1) or t.target local obj = p[target]:clone() local layer = p:layerOf(target) p:remove(target) p:insert(t.source, obj, nil, layer) end local function moveSourceToTarget (t, doc) local p = doc[t.pno] local obj = p[t.source]:clone() local layer = p:layerOf(t.source) p:insert(t.target, obj, t.select, layer) p:remove((t.target < t.source) and (t.source + 1) or t.source) end -- Move selection one step forward -- In other words: -- take object in front of nearest selection and -- place it behind furthest selection function MODEL:saction_forward() local p = self:page() local selection = self:selection() local furthest = nil local nearest = nil for i,obj,sel,layer in p:objects() do if sel then nearest = i if not furthest then furthest = i end end end if nearest == #p then self.ui:explain("already at front") return end local t = { label="move selection forward", pno = self.pno, vno = self.vno, source = nearest + 1, target = furthest, select = nil, undo = moveTargetToSource, redo = moveSourceToTarget, } self:register(t) end -- Move selection one step back -- In other words: -- take object behind furthest selection and -- place it in front of nearest selection function MODEL:saction_backward() local p = self:page() local selection = self:selection() local furthest = nil local nearest = nil for i,obj,sel,layer in p:objects() do if sel then nearest = i if not furthest then furthest = i end end end if furthest == 1 then self.ui:explain("already at back") return end local t = { label="move selection backward", pno = self.pno, vno = self.vno, source = furthest - 1, target = nearest + 1, select = nil, undo = moveTargetToSource, redo = moveSourceToTarget, } self:register(t) end -- Moves the primary selection just before the highest secondary. function MODEL:saction_before() local p = self:page() local prim = p:primarySelection() local sec = nil for i,obj,sel,layer in p:objects() do if sel == 2 then sec = i end end if not sec then self.ui:explain("no secondary selection") return end if prim == sec + 1 then self.ui:explain("nothing to do") return end local t = { label="move just before secondary selection", pno = self.pno, vno = self.vno, source = prim, target = sec + 1, select = 1, undo = moveTargetToSource, redo = moveSourceToTarget, } self:register(t) end -- Moves the primary selection just behind the lowest secondary. function MODEL:saction_behind() local p = self:page() local prim = p:primarySelection() local sec = nil for i,obj,sel,layer in p:objects() do if sel == 2 then sec = i break end end if not sec then self.ui:explain("no secondary selection") return end if prim == sec - 1 then self.ui:explain("nothing to do") return end local t = { label="move just behind secondary selection", pno = self.pno, vno = self.vno, source = prim, target = sec, select = 1, undo = moveTargetToSource, redo = moveSourceToTarget, } self:register(t) end function MODEL:selectionWithCursor() local data = self:page():xml("ipeselection") assert(data:sub(1,13) == "\n') f:write('\n') f:write(data) f:close() dd.model.ui:explain("Stylesheet saved to " .. s) end end function MODEL:action_style_sheets() local sheets = self.doc:sheets() local dd = { list = {}, model = self, modified = false } for i = 1,sheets:count() do dd.list[i] = sheets:sheet(i):clone() end local d = ipeui.Dialog(self.ui:win(), "Ipe style sheets") d:add("label1", "label", { label="Style sheets"}, 1, 1, 1, 4) d:add("list", "list", sheets_namelist(dd.list), 2, 1, 7, 3) d:add("add", "button", { label="&Add", action=function (d) sheets_add(d, dd) end }, 2, 4) d:add("del", "button", { label="Del", action=function (d) sheets_del(d, dd) end }, 3, 4) d:add("edit", "button", { label="Edit", action=function (d) sheets_edit(d, dd) end }, 4, 4) d:add("up", "button", { label="&Up", action=function (d) sheets_up(d, dd) end }, 5, 4) d:add("down", "button", { label="&Down", action=function (d) sheets_down(d, dd) end }, 6, 4) d:add("save", "button", { label="&Save", action=function (d) sheets_save(d, dd) end }, 7, 4) d:addButton("cancel", "&Cancel", "reject") d:addButton("ok", "&Ok", "accept") d:setStretch("column", 2, 1) if not d:execute() or not dd.modified then return end local t = { label="modify style sheets", final = ipe.Sheets(), style_sheets_changed = true, } for i,s in ipairs(dd.list) do t.final:insert(i, s) end t.undo = function (t, doc) t.final = doc:replaceSheets(t.original) end t.redo = function (t, doc) t.original = doc:replaceSheets(t.final) end self:register(t) self:action_check_style() end ---------------------------------------------------------------------- function MODEL:action_document_properties() local p = self.doc:properties() local d = ipeui.Dialog(self.ui:win(), "Ipe document properties") d:add("label1", "label", { label="Title"}, 1, 1) d:add("title", "input", {}, 1, 2, 1, 6) d:add("label2", "label", { label="Author"}, 2, 1) d:add("author", "input", {}, 2, 2, 1, 6) d:add("label3", "label", { label="Subject"}, 3, 1) d:add("subject", "input", {}, 3, 2, 1, 6) d:add("label4", "label", { label="Keywords"}, 4, 1) d:add("keywords", "input", {}, 4, 2, 1, 6) d:add("label5", "label", { label="Latex preamble"}, 5, 1) d:add("preamble", "text", {}, 5, 2, 2, 6) d:add("label6", "label", { label="Page mode"}, 7, 1) d:add("fullscreen", "checkbox", { label="&Full screen"}, 7, 2) d:add("numberpages", "checkbox", { label="&Number pages"}, 7, 3) d:add("label7", "label", { label="Created"}, 8, 1) d:add("created", "label", { label="" }, 8, 2) d:add("label8", "label", { label="Modified"}, 9, 1) d:add("modified", "label", { label="" }, 9, 2) d:add("label9", "label", { label="Creator" }, 10, 1) d:add("creator", "label", { label="" }, 10, 2) d:addButton("cancel", "&Cancel", "reject") d:addButton("ok", "&Ok", "accept") d:setStretch("column", 5, 1) d:setStretch("row", 6, 1) for n in pairs(p) do d:set(n, p[n]) end if not d:execute() then return end local t = { label="modify document properties", original = p, final = {}, } for n in pairs(p) do if n == "creator" or n == "created" or n == "modified" then t.final[n] = p[n] else t.final[n] = d:get(n) end end t.undo = function (t, doc) doc:setProperties(t.original) end t.redo = function (t, doc) doc:setProperties(t.final) end self:register(t) end ---------------------------------------------------------------------- function MODEL:saction_remove_clipping() local p = self:page() local prim = p:primarySelection() local obj = p[prim] assert(obj:type() == "group") local t = { label="remove clipping", pno=self.pno, vno=self.vno, primary=prim, original=obj:clone(), } t.undo = function (t, doc) doc[t.pno]:replace(t.primary, t.original) end t.redo = function (t, doc) doc[t.pno][t.primary]:setClip() doc[t.pno]:invalidateBBox(t.primary) end self:register(t) end function MODEL:saction_extract_clipping() local p = self:page() local prim = p:primarySelection() local obj = p[prim] assert(obj:type() == "group") local shape = obj:clip() transformShape(obj:matrix(), shape) local obj = ipe.Path(self.attributes, shape) self:creation("extract clipping path", obj) end function MODEL:saction_add_clipping() local p = self:page() local sel = self:selection() if #sel ~= 2 then self:warning("Must have exactly one two selected objects") return end local prim = sel[1] local sec = sel[2] if p[prim]:type() ~= "group" then prim = sel[2] sec = sel[1] end local obj = p[prim] if obj:type() ~= "group" or p[sec]:type() ~= "path" then self:warning("Must select exactly one group and one path") return end local shape = p[sec]:shape() transformShape(p[sec]:matrix(), shape) transformShape(obj:matrix():inverse(), shape) local t = { label = "add clipping", pno = self.pno, vno = self.vno, primary = prim, secondary = sec, original = obj:clone(), path = p[sec]:clone(), shape = shape, layer = p:layerOf(sec) } t.undo = function (t, doc) doc[t.pno]:insert(t.secondary, t.path, nil, t.layer) doc[t.pno]:replace(t.primary, t.original) end t.redo = function (t, doc) doc[t.pno][t.primary]:setClip(t.shape) doc[t.pno]:invalidateBBox(t.primary) doc[t.pno]:remove(t.secondary) end self:register(t) end ---------------------------------------------------------------------- ipe-7.1.4/src/ipe/lua/main.lua0000644000175000017500000002416412120621776015741 0ustar otfriedotfried---------------------------------------------------------------------- -- Ipe ---------------------------------------------------------------------- --[[ This file is part of the extensible drawing editor Ipe. Copyright (C) 1993-2013 Otfried Cheong Ipe is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. As a special exception, you have permission to link Ipe with the CGAL library and distribute executables, as long as you follow the requirements of the Gnu General Public License in regard to all of the software in the executable aside from CGAL. Ipe 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 General Public License for more details. You should have received a copy of the GNU General Public License along with Ipe; if not, you can find it at "http://www.gnu.org/copyleft/gpl.html", or write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. --]] -- order is important require "prefs" require "model" require "actions" require "tools" require "editpath" require "properties" require "shortcuts" require "mouse" ---------------------------------------------------------------------- -- short names V = ipe.Vector -- store the model for the first window -- Used only by MacOS file_open_event local first_model = nil ---------------------------------------------------------------------- function formatFromFileName(fname) local s = string.lower(fname:sub(-4)) if s == ".xml" or s == ".ipe" then return "xml" end if s == ".pdf" then return "pdf" end if s == ".eps" then return "eps" end return nil end function revertOriginal(t, doc) doc:set(t.pno, t.original) end function revertFinal(t, doc) doc:set(t.pno, t.final) end function indexOf(el, list) for i,n in ipairs(list) do if n == el then return i end end return nil end function symbolNames(sheet, prefix, postfix) local list = sheet:allNames("symbol") local result = {} for _, n in ipairs(list) do if n:sub(1, #prefix) == prefix and n:sub(-#postfix) == postfix then result[#result + 1] = n end end return result end function stripPrefixPostfix(list, m, mm) local result = {} for _, n in ipairs(list) do result[#result + 1] = n:sub(m, -mm-1) end return result end function arrowshapeToName(i, s) return s:match("^arrow/(.+)%(s?f?p?x%)$") end function colorString(color) if type(color) == "string" then return color end -- else must be table return string.format("(%g,%g,%g)", color.r, color.g, color.b) end function extractElements(p, selection) local r = {} local l = {} for i,j in ipairs(selection) do r[#r + 1] = p[j-i+1]:clone() l[#l + 1] = p:layerOf(j-i+1) p:remove(j-i+1) end return r, l end -- make a list of all values from stylesheets function allValues(sheets, kind) local syms = sheets:allNames(kind) local values = {} for _,sym in ipairs(syms) do values[#values + 1] = sheets:find(kind, sym) end return values end -- apply transformation to a shape function transformShape(matrix, shape) local result = {} for _,path in ipairs(shape) do if path.type == "ellipse" or path.type == "closedspline" then for i = 1,#path do path[i] = matrix * path[i] end else -- must be "curve" for _,seg in ipairs(path) do for i = 1,#seg do seg[i] = matrix * seg[i] end if seg.type == "arc" then seg.arc = matrix * seg.arc end end end end end function findStyle(w, dir) if dir and ipe.fileExists(dir .. "/" .. w) then return dir .. "/" .. w end for _, d in ipairs(config.styleDirs) do local s = d .. "/" .. w if ipe.fileExists(s) then return s end end end ---------------------------------------------------------------------- -- This function is called to launch a file on MacOS X function file_open_event(fname) if first_model and first_model.pristine then first_model:loadDocument(fname) else MODEL:new(fname) end end ---------------------------------------------------------------------- local win32_conversions = { PgDown=0x22, PgUp=0x21, Home=0x24, End=0x23, Left=0x25, Up=0x26, Right=0x27, Down=0x28, insert=0x2d, delete=0x2e, ["/"]= 0xbf, ["\\"]= 0xdc, ["-"]= 0xbd, ["="]= 0xbb, ["@"]= 0x40032, -- actually Shift+2 } function win32_shortcut_convert(s) local k = 0 local done = false while not done do if s:sub(1,5) == "Ctrl+" then s = s:sub(6) k = k + 0x20000 elseif s:sub(1,6) == "Shift+" then s = s:sub(7) k = k + 0x40000 elseif s:sub(1,4) == "Alt+" then s = s:sub(5) k = k + 0x10000 else done = true end end if s:sub(1,1) == "F" and tonumber(s:sub(2)) then return k + 0x6f + tonumber(s:sub(2)) elseif win32_conversions[s] then return k + win32_conversions[s] else return k + string.byte(s:sub(1,1)) end end function win32_shortcuts(ui) if config.toolkit ~= "win32" then return end local accel = {} for i in pairs(shortcuts) do local id = ui:actionId(i) local s = shortcuts[i] if type(s) == "table" then for j,s1 in ipairs(s) do accel[#accel+1] = win32_shortcut_convert(s1) accel[#accel+1] = id end elseif s then accel[#accel+1] = win32_shortcut_convert(s) accel[#accel+1] = id end end return accel end ---------------------------------------------------------------------- local function show_configuration() local s = config.version s = s .. "\nLua code: " .. package.path s = s .. "\nStyle directories: " .. table.concat(config.styleDirs, ", ") s = s .. "\nStyles for new documents: " .. table.concat(prefs.styles, ", ") s = s .. "\nAutosave file: " .. prefs.autosave_filename s = s .. "\nDocumentation: " .. config.docdir s = s .. "\nIpelets: " .. table.concat(config.ipeletDirs, ", ") s = s .. "\nLatex directory: " .. config.latexdir s = s .. "\nFontmap: " .. config.fontmap s = s .. "\nIcons: " .. config.icons s = s .. "\n" io.stdout:write(s) end local function usage() io.stderr:write("Usage: ipe { -sheet } [ ]\n") io.stderr:write("or: ipe -show-configuration\n") io.stderr:write("or: ipe --help\n") end -- check locale test1 = string.format("%g", 1.5) test2 = string.format("%s", tonumber("1.5")) if test1 ~= "1.5" or test2 ~= "1.5" then m = "Formatting the number 1.5 results in '" .. test1 .. "'. " .. "Reading '1.5' results in " .. test2 .. "
    " .. "Therefore Ipe will not work correctly when loading or saving files. " .. "Please report this problem.
    " .. "As a workaround, you can start Ipe from the commandline like this: " .. "
    export LANG=C\nexport LC_NUMERIC=C\nipe
    " ipeui.messageBox(nil, "critical", "Ipe is running with an incorrect locale", m) return end -------------------------------------------------------------------- local home = os.getenv("HOME") local ipeletpath = os.getenv("IPELETPATH") if ipeletpath then config.ipeletDirs = {} for w in string.gmatch(ipeletpath, "[^:;]+") do if w == "_" then w = config.system_ipelets end config.ipeletDirs[#config.ipeletDirs + 1] = w end else config.ipeletDirs = { config.system_ipelets } if config.platform ~= "win" then table.insert(config.ipeletDirs, 1, home .. "/.ipe/ipelets") if config.platform == "apple" then table.insert(config.ipeletDirs, 2, home .. "/Library/Ipe/Ipelets") end end end local ipestyles = os.getenv("IPESTYLES") if ipestyles then config.styleDirs = {} for w in string.gmatch(ipestyles, "[^:;]+") do if w == "_" then w = config.system_styles end config.styleDirs[#config.styleDirs + 1] = w end else config.styleDirs = { config.system_styles } if config.platform ~= "win" then table.insert(config.styleDirs, 1, home .. "/.ipe/styles") if config.platform == "apple" then table.insert(config.styleDirs, 2, home .. "/Library/Ipe/Styles") end end end -------------------------------------------------------------------- -- look for ipelets ipelets = {} for _,w in ipairs(config.ipeletDirs) do if ipe.fileExists(w) then for f in lfs.dir(w) do if f:sub(-4) == ".lua" then ft = {} ft._G = _G ft.ipe = ipe ft.ipeui = ipeui ft.math = math ft.string = string ft.table = table ft.assert = assert ft.shortcuts = shortcuts ft.prefs = prefs ft.mouse = mouse ft.ipairs = ipairs ft.pairs = pairs ft.print = print ft.tonumber = tonumber ft.tostring = tostring ft.name = f:sub(1,-5) ft.dllname = w .. "/" .. ft.name ff = assert(loadfile(w .. "/" .. f, "bt", ft)) -- setfenv(ff, ft) ff() -- if it has no label, then running it once was all if ft.label then ipelets[#ipelets + 1] = ft end end end end end -------------------------------------------------------------------- -- Windows provides the command line as one long string if config.toolkit == "win32" then local t = {} for w in string.gmatch(argv, "%S+") do t[#t+1] = w end argv = t end if #argv == 1 and argv[1] == "-show-configuration" then show_configuration() return end if #argv == 1 and (argv[1] == "--help" or argv[1] == "-h") then usage() return end -------------------------------------------------------------------- local first_file = nil local i = 1 local style_sheets = {} while i <= #argv do if argv[i] == "-sheet" then if i == #argv then usage() return end style_sheets[#style_sheets + 1] = argv[i+1] i = i + 2 else if i ~= #argv then usage() return end first_file = argv[i] i = i + 1 end end if #style_sheets > 0 then prefs.styles = style_sheets end config.styleList = {} for _,w in ipairs(prefs.styles) do if w:sub(-4) ~= ".isy" then w = w .. ".isy" end if not w:find("/") then w = findStyle(w) end config.styleList[#config.styleList + 1] = w end first_model = MODEL:new(first_file) mainloop(win32_shortcuts(first_model.ui)) ---------------------------------------------------------------------- ipe-7.1.4/src/ipe/appui_gtk.h0000644000175000017500000000652112120621776015662 0ustar otfriedotfried// -*- C++ -*- // -------------------------------------------------------------------- // Appui for GTK // -------------------------------------------------------------------- /* This file is part of the extensible drawing editor Ipe. Copyright (C) 1993-2013 Otfried Cheong Ipe is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. As a special exception, you have permission to link Ipe with the CGAL library and distribute executables, as long as you follow the requirements of the Gnu General Public License in regard to all of the software in the executable aside from CGAL. Ipe 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 General Public License for more details. You should have received a copy of the GNU General Public License along with Ipe; if not, you can find it at "http://www.gnu.org/copyleft/gpl.html", or write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ #ifndef APPUI_GTK_H #define APPUI_GTK_H #include "appui.h" using namespace ipe; // -------------------------------------------------------------------- class AppUi : public AppUiBase { public: AppUi(lua_State *L0, int model); ~AppUi(); virtual void action(String name); virtual void setupSymbolicNames(const Cascade *sheet); virtual void setAttributes(const AllAttributes &all, Cascade *sheet); virtual void setGridAngleSize(Attribute abs_grid, Attribute abs_angle); virtual void setLayers(const Page *page, int view); virtual void setZoom(double zoom); virtual void setActionsEnabled(bool mode); virtual void setNumbers(String vno, bool vm, String pno, bool pm); virtual void setNotes(String notes); virtual bool checkbox(lua_State *L); virtual WINID windowId(); virtual int actionId(const char *name); virtual bool closeWindow(); virtual bool actionState(const char *name); virtual void setActionState(const char *name, bool value); virtual void setWindowCaption(const char *s); virtual void explain(const char *s, int t); virtual void showWindow(int width, int height); // direct Lua methods virtual int setBookmarks(lua_State *L); virtual int showTool(lua_State *L); private: virtual void addRootMenu(int id, const char *name); void addItem(GtkMenuShell *shell, const char *title, const char *name); virtual void addItem(int id, const char *title, const char *name); virtual void startSubMenu(int id, const char *name); virtual void addSubItem(const char *title, const char *name); virtual MENUHANDLE endSubMenu(); virtual void setMouseIndicator(const char *s); static void menuitem_cb(GtkWidget *item, gpointer data); private: struct SAction { String name; GtkWidget *menuItem; }; std::vector iActions; GtkWidget *iWindow; GtkWidget *iRootMenu[ENumMenu]; GtkWidget *iSubMenu[ENumMenu]; GtkWidget *iStatusBar; int iStatusBarContextid; GtkWidget *iMousePosition; GtkWidget *iResolution; GtkAccelGroup *iAccelGroup; }; // -------------------------------------------------------------------- #endif ipe-7.1.4/src/ipe/ipe.ico0000644000175000017500000000137612120621776015002 0ustar otfriedotfried è( @€€€€€€€€€ÀÀÀ€€€ÿÿÿÿÿÿÿÿÿÿÿÿ »°»° »°»° °ÿÿðÿÿÿÿÿÿÿðÿÿÿÿðÿÿÿÿðÿÿÿÿðÿÿÿÿðÿÿÿÿðÿÿÿÿÿð ™™™ ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿáÇÿÿáÇÿÿøÿÿðÿþpÿþ`þ@þ@þÿþÿþÿÿÿÿÿÿ€ÿÿÀÿÿàÿÿðÿÿàÿÿàÿÿàÿÿàÿÿðÿÿøÿÿÿÿÿÿÿÿÿÿÿÿÿipe-7.1.4/src/ipe/controls_qt.h0000644000175000017500000000610412120621776016243 0ustar otfriedotfried// -*- C++ -*- // -------------------------------------------------------------------- // Special widgets for QT // -------------------------------------------------------------------- /* This file is part of the extensible drawing editor Ipe. Copyright (C) 1993-2013 Otfried Cheong Ipe is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. As a special exception, you have permission to link Ipe with the CGAL library and distribute executables, as long as you follow the requirements of the Gnu General Public License in regard to all of the software in the executable aside from CGAL. Ipe 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 General Public License for more details. You should have received a copy of the GNU General Public License along with Ipe; if not, you can find it at "http://www.gnu.org/copyleft/gpl.html", or write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ #ifndef CONTROLS_QT_H #define CONTROLS_QT_H #include "ipelib.h" #include using namespace ipe; // -------------------------------------------------------------------- class LayerBox : public QListWidget { Q_OBJECT public: LayerBox(QWidget *parent = 0); void set(const Page *page, int view); signals: void activated(String name, String layer); void showLayerBoxPopup(Vector v, String layer); public slots: void layerChanged(QListWidgetItem *item); protected: virtual void mouseReleaseEvent(QMouseEvent *e); virtual void mousePressEvent(QMouseEvent *e); void addAction(QMenu *m, QListWidgetItem *item, String name, const QString &text); private: bool iInSet; }; // -------------------------------------------------------------------- class PathView : public QWidget { Q_OBJECT public: PathView(QWidget* parent = 0, Qt::WFlags f = 0); void set(const AllAttributes &all, Cascade *sheet); virtual QSize sizeHint() const; signals: void activated(String name); void showPathStylePopup(Vector v); protected: virtual void paintEvent(QPaintEvent *ev); virtual void mouseReleaseEvent(QMouseEvent *e); virtual void mousePressEvent(QMouseEvent *e); virtual bool event(QEvent *ev); private: Cascade *iCascade; AllAttributes iAll; }; // -------------------------------------------------------------------- class PageSorter : public QListWidget { Q_OBJECT public: PageSorter(Document *doc, int width, QWidget *parent = 0); int pageAt(int r) const; public slots: void deletePages(); void cutPages(); void insertPages(); private: virtual void contextMenuEvent(QContextMenuEvent *event); private: Document *iDoc; QList iCutList; int iActionRow; }; // -------------------------------------------------------------------- #endif ipe-7.1.4/src/ipe/tools.h0000644000175000017500000000607512120621776015043 0ustar otfriedotfried// -*- C++ -*- // -------------------------------------------------------------------- // Canvas tools // -------------------------------------------------------------------- /* This file is part of the extensible drawing editor Ipe. Copyright (C) 1993-2013 Otfried Cheong Ipe is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. As a special exception, you have permission to link Ipe with the CGAL library and distribute executables, as long as you follow the requirements of the Gnu General Public License in regard to all of the software in the executable aside from CGAL. Ipe 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 General Public License for more details. You should have received a copy of the GNU General Public License along with Ipe; if not, you can find it at "http://www.gnu.org/copyleft/gpl.html", or write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ #ifndef TOOLS_H #define TOOLS_H #include "ipetool.h" #include "ipecanvas.h" // avoid including Lua headers here typedef struct lua_State lua_State; // -------------------------------------------------------------------- using namespace ipe; extern void push_button(lua_State *L, int button); class IpeTransformTool : public TransformTool { public: IpeTransformTool(CanvasBase *canvas, Page *page, int view, TType type, bool withShift, lua_State *L0, int method); ~IpeTransformTool(); virtual void report(); private: lua_State *L; int iMethod; }; class LuaTool : public Tool { public: LuaTool(CanvasBase *canvas, lua_State *L0, int luatool); ~LuaTool(); void setColor(Color color) { iColor = color; } virtual void mouseButton(int button, bool press); virtual void mouseMove(); virtual bool key(int code, int modifiers, String text); protected: lua_State *L; int iLuaTool; Color iColor; }; class ShapeTool : public LuaTool { public: enum TMarkType { EVertex = 1, ESplineCP, EBezierCP, ECenter, ERadius, EMinor, ECurrent, EScissor, ENumMarkTypes }; ShapeTool(CanvasBase *canvas, lua_State *L0, int luatool); void setShape(Shape shape, int which = 0, double pen=1.0); void clearMarks(); void addMark(const Vector &v, TMarkType t); virtual void draw(Painter &painter) const; private: double iPen; Shape iShape; Shape iAuxShape; struct SMark { Vector v; TMarkType t; }; std::vector iMarks; }; class PasteTool : public LuaTool { public: PasteTool(CanvasBase *canvas, lua_State *L0, int luatool, Object *obj); ~PasteTool(); void setMatrix(Matrix m) { iMatrix = m; } virtual void draw(Painter &painter) const; private: Object *iObject; Matrix iMatrix; }; // -------------------------------------------------------------------- #endif ipe-7.1.4/src/ipe/controls_qt.cpp0000644000175000017500000002371012120621776016600 0ustar otfriedotfried// -------------------------------------------------------------------- // Special widgets for QT // -------------------------------------------------------------------- /* This file is part of the extensible drawing editor Ipe. Copyright (C) 1993-2013 Otfried Cheong Ipe is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. As a special exception, you have permission to link Ipe with the CGAL library and distribute executables, as long as you follow the requirements of the Gnu General Public License in regard to all of the software in the executable aside from CGAL. Ipe 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 General Public License for more details. You should have received a copy of the GNU General Public License along with Ipe; if not, you can find it at "http://www.gnu.org/copyleft/gpl.html", or write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ #include "controls_qt.h" #include "ipethumbs.h" #include "ipecairopainter.h" #include "ipecanvas_qt.h" #include #include #include #include // -------------------------------------------------------------------- LayerBox::LayerBox(QWidget *parent) : QListWidget(parent) { setFocusPolicy(Qt::NoFocus); setSelectionMode(NoSelection); iInSet = false; connect(this, SIGNAL(itemChanged(QListWidgetItem *)), SLOT(layerChanged(QListWidgetItem *))); } void LayerBox::layerChanged(QListWidgetItem *item) { if (iInSet) return; if (item->checkState() == Qt::Checked) emit activated("selecton", IpeQ(item->text())); else emit activated("selectoff", IpeQ(item->text())); } void LayerBox::set(const Page *page, int view) { iInSet = true; clear(); for (int i = 0; i < page->countLayers(); ++i) { // int i = idx[j].second; QListWidgetItem *item = new QListWidgetItem(QIpe(page->layer(i)), this); item->setFlags(Qt::ItemIsUserCheckable|Qt::ItemIsEnabled); item->setCheckState(page->visible(view, i) ? Qt::Checked : Qt::Unchecked); if (page->layer(i) == page->active(view)) item->setBackgroundColor(Qt::yellow); if (page->isLocked(i)) item->setBackground(QColor(255, 220, 220)); if (!page->hasSnapping(i)) item->setForeground(Qt::gray); } iInSet = false; } void LayerBox::mousePressEvent(QMouseEvent *ev) { QListWidgetItem *item = itemAt(ev->pos()); if (item && ev->button()== Qt::LeftButton && ev->x() > 30) { emit activated("active", IpeQ(item->text())); } QListWidget::mousePressEvent(ev); } void LayerBox::mouseReleaseEvent(QMouseEvent *ev) { QListWidgetItem *item = itemAt(ev->pos()); if (item && ev->button() == Qt::RightButton) { // make popup menu emit showLayerBoxPopup(Vector(ev->globalPos().x(), ev->globalPos().y()), IpeQ(item->text())); } else QListWidget::mouseReleaseEvent(ev); } // -------------------------------------------------------------------- PathView::PathView(QWidget* parent, Qt::WFlags f) : QWidget(parent, f) { iCascade = 0; } void PathView::set(const AllAttributes &all, Cascade *sheet) { iCascade = sheet; iAll = all; update(); } void PathView::paintEvent(QPaintEvent *ev) { QSize s = size(); int w = s.width(); int h = s.height(); cairo_surface_t *sf = cairo_image_surface_create(CAIRO_FORMAT_RGB24, w, h); cairo_t *cc = cairo_create(sf); cairo_set_source_rgb(cc, 1, 1, 0.8); cairo_rectangle(cc, 0, 0, w, h); cairo_fill(cc); if (iCascade) { cairo_translate(cc, 0, h); double zoom = 2.0; cairo_scale(cc, zoom, -zoom); Vector v0 = (1.0/zoom) * Vector(0.1 * w, 0.5 * h); Vector v1 = (1.0/zoom) * Vector(0.7 * w, 0.5 * h); Vector u1 = (1.0/zoom) * Vector(0.88 * w, 0.8 * h); Vector u2 = (1.0/zoom) * Vector(0.80 * w, 0.5 * h); Vector u3 = (1.0/zoom) * Vector(0.88 * w, 0.2 * h); Vector u4 = (1.0/zoom) * Vector(0.96 * w, 0.5 * h); CairoPainter painter(iCascade, 0, cc, 3.0, false); painter.setPen(iAll.iPen); painter.setDashStyle(iAll.iDashStyle); painter.setStroke(iAll.iStroke); painter.setFill(iAll.iFill); painter.pushMatrix(); painter.newPath(); painter.moveTo(v0); painter.lineTo(v1); painter.drawPath(EStrokedOnly); if (iAll.iFArrow) Path::drawArrow(painter, v1, Angle(0), iAll.iFArrowShape, iAll.iFArrowSize, 100.0); if (iAll.iRArrow) Path::drawArrow(painter, v0, Angle(IpePi), iAll.iRArrowShape, iAll.iRArrowSize, 100.0); painter.setDashStyle(Attribute::NORMAL()); painter.setTiling(iAll.iTiling); painter.newPath(); painter.moveTo(u1); painter.lineTo(u2); painter.lineTo(u3); painter.lineTo(u4); painter.closePath(); painter.drawPath(iAll.iPathMode); painter.popMatrix(); } cairo_surface_flush(sf); cairo_destroy(cc); QPainter qPainter; qPainter.begin(this); QRect r = ev->rect(); QImage bits(cairo_image_surface_get_data(sf), w, h, QImage::Format_RGB32); qPainter.drawImage(r.left(), r.top(), bits, r.left(), r.top(), r.width(), r.height()); qPainter.end(); cairo_surface_destroy(sf); } QSize PathView::sizeHint() const { return QSize(120, 40); } void PathView::mousePressEvent(QMouseEvent *ev) { QSize s = size(); if (ev->button()== Qt::LeftButton && ev->x() < s.width() * 3 / 10) { emit activated(iAll.iRArrow ? "rarrow|false" : "rarrow|true"); } else if (ev->button()== Qt::LeftButton && ev->x() > s.width() * 4 / 10 && ev->x() < s.width() * 72 / 100) { emit activated(iAll.iFArrow ? "farrow|false" : "farrow|true"); update(); } else if (ev->button()== Qt::LeftButton && ev->x() > s.width() * 78 / 100) { switch (iAll.iPathMode) { case EStrokedOnly: emit activated("pathmode|strokedfilled"); break; case EStrokedAndFilled: emit activated("pathmode|filled"); break; case EFilledOnly: emit activated("pathmode|stroked"); break; } update(); } } void PathView::mouseReleaseEvent(QMouseEvent *ev) { if (ev->button()== Qt::RightButton) emit showPathStylePopup(Vector(ev->globalPos().x(), ev->globalPos().y())); } bool PathView::event(QEvent *ev) { if (ev->type() != QEvent::ToolTip) return QWidget::event(ev); QHelpEvent *hev = (QHelpEvent *) ev; QSize s = size(); QString tip; if (hev->x() < s.width() * 3 / 10) tip = "Toggle reverse arrow"; else if (hev->x() > s.width() * 4 / 10 && hev->x() < s.width() * 72 / 100) tip = "Toggle forward arrow"; else if (hev->x() > s.width() * 78 / 100) tip = "Toggle stroked/stroked & filled/filled"; if (!tip.isNull()) QToolTip::showText(hev->globalPos(), tip, this); return true; } // -------------------------------------------------------------------- PageSorter::PageSorter(Document *doc, int itemWidth, QWidget *parent) : QListWidget(parent) { iDoc = doc; setViewMode(QListView::IconMode); setSelectionMode(QAbstractItemView::ExtendedSelection); setResizeMode(QListView::Adjust); setWrapping(true); setUniformItemSizes(true); setFlow(QListView::LeftToRight); setSpacing(10); setMovement(QListView::Static); Thumbnail r(iDoc, itemWidth); setGridSize(QSize(itemWidth, r.height() + 50)); setIconSize(QSize(itemWidth, r.height())); for (int i = 0; i < doc->countPages(); ++i) { Page *p = doc->page(i); Buffer b = r.render(p, p->countViews() - 1); QImage bits((const uchar *) b.data(), itemWidth, r.height(), QImage::Format_RGB32); // need to copy bits since buffer b is temporary QIcon icon(QPixmap::fromImage(bits.copy())); QString s; QString t = QString::fromUtf8(p->title().z()); if (t != "") { s.sprintf("%d: ", i+1); s += t; } else { s.sprintf("Page %d", i+1); } QListWidgetItem *item = new QListWidgetItem(icon, s); item->setFlags(Qt::ItemIsSelectable|Qt::ItemIsEnabled); item->setToolTip(s); item->setData(Qt::UserRole, QVariant(i)); // page number addItem(item); } } int PageSorter::pageAt(int r) const { return item(r)->data(Qt::UserRole).toInt(); } void PageSorter::deletePages() { QList items = selectedItems(); for (int i = 0; i < items.count(); ++i) { int r = row(items[i]); QListWidgetItem *item = takeItem(r); delete item; } } void PageSorter::cutPages() { // delete items in old cut list for (int i = 0; i < iCutList.count(); ++i) delete iCutList[i]; iCutList.clear(); QList items = selectedItems(); for (int i = 0; i < items.count(); ++i) { int r = row(items[i]); QListWidgetItem *item = takeItem(r); iCutList.append(item); } } void PageSorter::insertPages() { // deselect everything for (int i = 0; i < count(); ++i) item(i)->setSelected(false); int r = (iActionRow >= 0) ? iActionRow : count(); for (int i = 0; i < iCutList.count(); ++i) { insertItem(r, iCutList[i]); item(r++)->setSelected(true); } iCutList.clear(); } void PageSorter::contextMenuEvent(QContextMenuEvent *ev) { ev->accept(); QListWidgetItem *item = itemAt(ev->pos()); iActionRow = row(item); QMenu *m = new QMenu(); QAction *action_delete = new QAction("&Delete", this); connect(action_delete, SIGNAL(triggered()), SLOT(deletePages())); QAction *action_cut = new QAction("&Cut", this); connect(action_cut, SIGNAL(triggered()), SLOT(cutPages())); QAction *action_insert = new QAction("&Insert", this); connect(action_insert, SIGNAL(triggered()), SLOT(insertPages())); if (selectedItems().count() > 0) { m->addAction(action_delete); m->addAction(action_cut); } if (iCutList.count() > 0) m->addAction(action_insert); m->exec(ev->globalPos()); delete m; } // -------------------------------------------------------------------- ipe-7.1.4/src/ipe/main.cpp0000644000175000017500000002101412120621776015150 0ustar otfriedotfried// -------------------------------------------------------------------- // Main function // -------------------------------------------------------------------- /* This file is part of the extensible drawing editor Ipe. Copyright (C) 1993-2013 Otfried Cheong Ipe is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. As a special exception, you have permission to link Ipe with the CGAL library and distribute executables, as long as you follow the requirements of the Gnu General Public License in regard to all of the software in the executable aside from CGAL. Ipe 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 General Public License for more details. You should have received a copy of the GNU General Public License along with Ipe; if not, you can find it at "http://www.gnu.org/copyleft/gpl.html", or write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ #include "ipebase.h" #include "ipelua.h" #include #include #ifdef IPEUI_QT #include "appui_qt.h" #include #include #include #include #endif #ifdef IPEUI_WIN32 #define _WIN32_WINNT 0x0501 #define _WIN32_IE 0x0500 #include #include extern void ipe_init_canvas(HINSTANCE hInstance); extern void ipe_init_appui(HINSTANCE hInstance, int nCmdShow); #endif #ifdef IPEUI_GTK #include #endif using namespace ipe; using namespace ipelua; extern int luaopen_ipeui(lua_State *L); extern int luaopen_appui(lua_State *L); extern int luaopen_lfs (lua_State *L); // -------------------------------------------------------------------- String ipeIconDirectory() { static String iconDir; if (iconDir.empty()) { const char *p = getenv("IPEICONDIR"); #ifdef WIN32 String s(p ? p : Platform::ipeDir("icons\\")); #else String s(p ? p : IPEICONDIR); if (s.right(1) != "/") s += "/"; #endif iconDir = s; } return iconDir; } static int traceback (lua_State *L) { if (!lua_isstring(L, 1)) /* 'message' not a string? */ return 1; /* keep it intact */ lua_rawgeti(L, LUA_REGISTRYINDEX, LUA_RIDX_GLOBALS); lua_getfield(L, -1, "debug"); if (!lua_istable(L, -1)) { lua_pop(L, 2); return 1; } lua_getfield(L, -1, "traceback"); if (!lua_isfunction(L, -1)) { lua_pop(L, 3); return 1; } lua_pushvalue(L, 1); // pass error message lua_pushinteger(L, 2); // skip this function and traceback lua_call(L, 2, 1); // call debug.traceback return 1; } static void setup_config(lua_State *L, const char *var, const char *env, const char *conf) { const char *p = env ? getenv(env) : 0; #ifdef WIN32 push_string(L, p ? p : Platform::ipeDir(conf)); #else lua_pushstring(L, p ? p : conf); #endif lua_setfield(L, -2, var); } // -------------------------------------------------------------------- static lua_State *setup_lua() { lua_State *L = luaL_newstate(); luaL_openlibs(L); luaopen_ipe(L); luaopen_lfs(L); luaopen_ipeui(L); luaopen_appui(L); return L; } static void setup_globals(lua_State *L, int width, int height, const char *tk) { lua_getglobal(L, "package"); const char *luapath = getenv("IPELUAPATH"); if (luapath) lua_pushstring(L, luapath); else { #ifdef WIN32 push_string(L, Platform::ipeDir("lua/?.lua")); #else lua_pushstring(L, IPELUADIR "/?.lua"); #endif } lua_setfield(L, -2, "path"); lua_newtable(L); // config table #if defined(WIN32) lua_pushliteral(L, "win"); #elif defined(__APPLE__) lua_pushliteral(L, "apple"); #else lua_pushliteral(L, "unix"); #endif lua_setfield(L, -2, "platform"); lua_pushstring(L, tk); lua_setfield(L, -2, "toolkit"); #ifdef WIN32 setup_config(L, "system_styles", 0, "styles"); setup_config(L, "system_ipelets", 0, "ipelets"); setup_config(L, "docdir", "IPEDOCDIR", "doc"); #else setup_config(L, "system_styles", 0, IPESTYLEDIR); setup_config(L, "system_ipelets", 0, IPELETDIR); setup_config(L, "docdir", "IPEDOCDIR", IPEDOCDIR); #endif push_string(L, Platform::fontmapFile()); lua_setfield(L, -2, "fontmap"); push_string(L, Platform::latexDirectory()); lua_setfield(L, -2, "latexdir"); push_string(L, ipeIconDirectory()); lua_setfield(L, -2, "icons"); lua_pushfstring(L, "Ipe %d.%d.%d", IPELIB_VERSION / 10000, (IPELIB_VERSION / 100) % 100, IPELIB_VERSION % 100); lua_setfield(L, -2, "version"); lua_createtable(L, 0, 2); lua_pushinteger(L, width); lua_rawseti(L, -2, 1); lua_pushinteger(L, height); lua_rawseti(L, -2, 2); lua_setfield(L, -2, "screen_geometry"); lua_setglobal(L, "config"); } static bool lua_run_ipe(lua_State *L, lua_CFunction fn) { lua_pushcfunction(L, fn); lua_setglobal(L, "mainloop"); // run Ipe lua_pushcfunction(L, traceback); assert(luaL_loadstring(L, "require \"main\"") == 0); if (lua_pcall(L, 0, 0, -2)) { const char *errmsg = lua_tostring(L, -1); fprintf(stderr, "%s\n", errmsg); return false; } return true; } // -------------------------------------------------------------------- #ifdef IPEUI_QT int mainloop(lua_State *L) { QApplication::exec(); return 0; } int main(int argc, char *argv[]) { Platform::initLib(IPELIB_VERSION); lua_State *L = setup_lua(); IpeApp a(L, argc, argv); a.setQuitOnLastWindowClosed(true); setlocale(LC_NUMERIC, "C"); // create table with arguments lua_createtable(L, 0, argc - 1); for (int i = 1; i < argc; ++i) { lua_pushstring(L, argv[i]); lua_rawseti(L, -2, i); } lua_setglobal(L, "argv"); QRect r = a.desktop()->screenGeometry(); setup_globals(L, r.width(), r.height(), "qt"); lua_run_ipe(L, mainloop); lua_close(L); return 0; } #endif // -------------------------------------------------------------------- #ifdef IPEUI_WIN32 int mainloop(lua_State *L) { luaL_argcheck(L, lua_istable(L, 1), 1, "Argument is not a table"); int no = lua_objlen(L, 1); luaL_argcheck(L, no > 0, 1, "Table must have at least one shortcut"); std::vector accel; for (int i = 1; i <= no; i += 2) { lua_rawgeti(L, 1, i); lua_rawgeti(L, 1, i+1); ACCEL a; int key = luaL_checkinteger(L, -2); a.key = key & 0xffff; a.cmd = luaL_checkinteger(L, -1); a.fVirt = (((key & 0x10000) ? FALT : 0) | ((key & 0x20000) ? FCONTROL : 0) | ((key & 0x40000) ? FSHIFT : 0) | FVIRTKEY); accel.push_back(a); lua_pop(L, 2); } HACCEL hAccel = CreateAcceleratorTable(&accel[0], accel.size()); MSG msg; while (GetMessage(&msg, NULL, 0, 0) > 0) { HWND target = GetAncestor(msg.hwnd, GA_ROOT); if (!TranslateAccelerator(target, hAccel, &msg)) { TranslateMessage(&msg); DispatchMessage(&msg); } } return 0; } int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow) { Platform::initLib(IPELIB_VERSION); INITCOMMONCONTROLSEX icex; icex.dwSize = sizeof(INITCOMMONCONTROLSEX); icex.dwICC = ICC_COOL_CLASSES | ICC_BAR_CLASSES | ICC_USEREX_CLASSES | ICC_STANDARD_CLASSES; InitCommonControlsEx(&icex); ipe_init_canvas(hInstance); ipe_init_appui(hInstance, nCmdShow); lua_State *L = setup_lua(); // setup command line argument lua_pushstring(L, lpCmdLine); lua_setglobal(L, "argv"); int cx = GetSystemMetrics(SM_CXSCREEN); int cy = GetSystemMetrics(SM_CYSCREEN); setup_globals(L, cx, cy, "win32"); lua_run_ipe(L, mainloop); lua_close(L); return 0; } #endif // -------------------------------------------------------------------- #ifdef IPEUI_GTK int mainloop(lua_State *L) { gtk_main(); return 0; } int main(int argc, char *argv[]) { Platform::initLib(IPELIB_VERSION); gtk_init(&argc, &argv); lua_State *L = setup_lua(); // create table with arguments lua_createtable(L, 0, argc - 1); for (int i = 1; i < argc; ++i) { lua_pushstring(L, argv[i]); lua_rawseti(L, -2, i); } lua_setglobal(L, "argv"); GdkScreen* screen = gdk_screen_get_default(); int width = gdk_screen_get_width(screen); int height = gdk_screen_get_height(screen); ipeDebug("Screen resolution is (%d x %d)", width, height); setup_globals(L, width, height, "gtk"); lua_run_ipe(L, mainloop); lua_close(L); return 0; } #endif // -------------------------------------------------------------------- ipe-7.1.4/src/ipe/icons/0000755000175000017500000000000012120621776014635 5ustar otfriedotfriedipe-7.1.4/src/ipe/icons/mode_polygons.png0000644000175000017500000000037312120621776020224 0ustar otfriedotfried‰PNG  IHDRàw=øbKGDßB{÷7:°IDATxÚí•Aƒ E?ÄSÐÄêUè¹íU¬]xq#É„fF¥nú7&ŒïCà rs쉌ﯳH¼€aZ0LËáUÖxßz‹:ø¼ž|,X-&_1sÚ¿Z%¦ÊQó qT5æ"GJsͱ œ&ãRîóº?’q©oxý7}`͸”ûR½Ù!ßÓ¦vùUQÊõÃrÙ‰ïÉ{JÊÖNPãoyÌ:ËŸÒ…stÒP¨DIEND®B`‚ipe-7.1.4/src/ipe/icons/cut.png0000644000175000017500000000223112120621776016134 0ustar otfriedotfried‰PNG  IHDRÄ´l;bKGDÿÿÿ ½§“ pHYs  Í›žtIMEÖ 21A|ç§&IDAT8Ë…“]H\GÇÿ3;wïݬ&ñccÌ®º…6±41¶%Õˆ†$ÚÒ–>„€´I_¥6­ôAK‹…@’´!¤!!?‚±†’S‰iе5%&i¤cÕm4«î÷Ý{gîô!+Ȳ®¸ ÜsøÍ9ÿ9‡ I_Ÿ³,«Ü4ͪ¶–ö;Ø@§ÏžjЩiŽùæ?õ$Çir2¥´ìÀ2äæä#4Mûêí·Þ¥Ô}úì©kiÁN§óÃ7^“x ŸƒÚ´o/žïHý¦»«Ç½ËͲ¶gãPÕaìÌÛ¹/-˜sîÎÍqª€öÅãñwËË* „€¦iˆD#iÁñx|jèú5Ën·Ca òòòmW¾»<²>'33sð`y8 ”âÖèÏ…B­iÁŽ-=]"ºƒ”%ûö#YWm¥¢Ôã.„”OŸ 7VÛZÚ»Ò‚ÛZÚ¸484 N'¤”xyÿ«èëïy?=RÎ9c½=‚X,Zšê’+F[K{½®ë‡Ý—„äæº w_¼t¡kû¶¬­šê€”wÿ€ªª½‰b6'ÔøÛøÙ²åä`y%233?)(,‚””ÌÍÏ'›šßÛhS‚ÛZÚ{-ËýåÎmËf³AQ¨ªÁ9!øiøG„B¡êtsNÓÄ>øgúo "!¥Dñ1=3 f³=H·•`Û(psx$P]sÔñßÔTeqI)LÓ„að?|€M;°‰ÒUŒâÏ:ŒøÌ &ÿœ@qq1‰…BXšz„A»½c30IþqðnÓ´JHmœsmïÞ—ˆßáÀ¿ã¿£ ì5äÄb˜œ¼/UÆtKÊþ€®Q̤ÚíŠÍöyQVV¾¦(P賆Ægge"W–0- ºiâñÊŠÏâËc†q>¥w²uË•¿‹ù'}¾4ŠÅp†gXíñ †gÃaø£QLú|+«±˜Ë•/¤lð¸kR{ÖWx½^$‚Åp¸Ï¢Û¡(Xaw÷ô7˜XáPBt/†Ã}þH^¯Ñh}j°i>¯1†ˆað%!†TÆœv;(!ó'€ë´:à{JȼÓn‡ÊXÃ’CÃàc†ñÂzkÙÚÄäž ®c«¦¡„±žìlL,,,ÍrÞÀ @À,ç½ðùê^ñxvÌ-/ßPãA]å @`4q µ3vy.@†¢0‡ªâžÏ‡e)ýˆó~Ù‰ÏÕÄùÕ§RŽÝóùàPUd( › `1Ö@Mì!ë…]Õ´*eµ%%ñIyó¤i$bVR‡¼“±Ú]”V3BDœ[ïëú9|­b’4z$á;M@”¤‘\ëÐJ@ĺ »,ø§ëÕŸ„î´¼IEND®B`‚ipe-7.1.4/src/ipe/icons/mode_arc3.png0000644000175000017500000000043412120621776017200 0ustar otfriedotfried‰PNG  IHDRàw=øbKGDßB{÷7:ÑIDATxÚíÔ1NQÆñß{cèq·ÐÎP‘`éLl=ŠövörKHH0ÀJ…Þ€pmvÍj6aÙ¼ øwóÞdfÞÌ|=Û&iè7Àú8E·8ÿÄžñˆi£ïÃ^^µ³Éb„;¼à ßÅU‡8Ã5Np‹‡µ Òñ|œË&‹F/­),é„îy:ž+‹ƒƒŸYYyŒ!ßà÷m‚Õµèe1¸`Tƒ]⪲!ÁyÂQLÑ­6^+òh_źéòÄØ¢(ü*9”r÷ì ?!±3ëꪀ5IEND®B`‚ipe-7.1.4/src/ipe/icons/mode_splinegons.png0000644000175000017500000000023212120621776020525 0ustar otfriedotfried‰PNG  IHDRþzþxPLTEÿ€€ªtRNS@æØfBIDAT™MÌ¡!CÑ ƒ8‰L T°4v³×¥P Á‘Ì1§,h T Hs§ýÕ8¼ Kñp„%ü>ù¸³˜.H ¡þIEND®B`‚ipe-7.1.4/src/ipe/icons/mode_translate.png0000644000175000017500000000117612120621776020351 0ustar otfriedotfried‰PNG  IHDRÄ´l;bKGDÿÿÿ ½§“ pHYs  šœtIMEÖ %{¯ IDAT8˵•AkA†Ÿl675Á*ZŒ—B¡x¦'!? öà!‹þŽü‚þ ñä­Ð“„"ÞE¡=ˆE1´Ò¦JšhM6»Y³üf™l¶ÍîÁfgŸyç}?XH8V·wî’b) 'iàFRh£¹E¸‘úéË ià‹‡P`¾l.Ú°·»ÀæƒMÞðáð}"¯wÚ­ŒXX9sf-Xy°m+.ƒ@¦åN»uëq$ý¹q£´»~Y ™¸ôã|l4·B¿õQ©UY_+«w¡òL Ïç°r&¶mÅ*üâ8ÞÄÇu'sðÿ¦Ø NòÞî>ëkå0}UÑNÑ×ã 3áéðHuý+ú|®+̈š®f–<3Žã©mÀ‚N»•)C›‡`¥,+e×V·wÎÍ›øª-‡"bðä?ZMÀÐ,É6Pn+*´J­ŠëN¨Ôªh}~¸ ”ä;S·6+JÕÕm¹j (ºƒo¯Ž×›õú½þET÷Ýó'þèÜuQ>Õ‡`ÏŠr 0ýQÏ÷^ÿ,6êõзϞŽ{Ÿ»À¿eî 8P`åq §MÅ7û£ówqöò¨_xüýðÅ#çÇǯ@_j ìëáE[K÷zI,Yî,ßXOoJ ¯Ýz–ä ö—<çÆ_â Y…2 IEND®B`‚ipe-7.1.4/src/ipe/icons/delete.png0000644000175000017500000000227312120621776016611 0ustar otfriedotfried‰PNG  IHDRÄ´l;bKGDùC» pHYs  šœtIMEÖ n tEXtCommentid logo†Æw¹-IDAT8Ë­”mh[UÇÿçÜ{“¦m^zoú’l¶·©m­Û,V;ié`/àuŠSý hôƒ0ßð­ £Ã/"ƒáœ~gK7«"Ò•4j;f-ëÚ”66Mº4éM››·{Žš¦ n8Üçù_·ç<<[ôÑɇt=±ÿC¥Ÿ¼zìÍî\ÜúS×û^ì~ ét:ïq΋ ! INŸ9õ<€M°z¸÷==ë)C"‘@,+nä’$RZà9€z¸wãR çíWŽb" A›þš¦aaaáºP„X,–¼Çƒ¦ixøÑÇ}ß÷ä[1Ô‘öÇ‹Åà÷ûÿµòU€ÇãÁÜb†-W¥TØcIñgb;ž9ñS ׯÿPÀvìÜRCÌìÚ{7¢CŸ½ŒË¯\>°[ÁŠüh…à‰œq³DÔ{{/€ ëfB9¸À‰ŽóÇŽ>qm9±ŸùôtzÿþƒÒØØ¯hoßK½^oª««Ë4~é÷ÌîÖ=&ßE_ªíÎ6i||<ÝÚÚj ‡—Øå?.eŸzòi‹,ËÑóýÎ7^{‹ÐÍñ!ÙL6³¢T:WãñÕXMµË`Œkn÷6Ã0X¤¢B6DIйªÝ+zBɲ #Ë–\.·Ù¬›Ã¾b6—¢©ÉýyäGEV556avΟ®­½…E£Ëº\!'ãqÍRSSÍÖÖÖXMM5!D­W…ªª*:˜e²,3‹Ù"å ÍÍ€¡­ãžÎˆ³Ò™QëêuEqRJÉŒÕVž•+dÝfµn·kYQœ„qÆì6»QVVÆʼnÉÉ 4[& AÐÔܬ^º2©Ö©‡Ý.†#¡qEq–ªªºj³Y¿掱±_¶™L¬Örcêê”åÈCÔ‚¡ÐbªœÐaI”x_ÿÙh:›šÑ´X´à+­¼´¼m9²4KI|÷÷ôö-عk’ÉT*¼Îú§1:êÃY‰ÅbîâµÉ‘njiº˜ÔõÀôÔÌýþ¿Qç©ý\E><2|çœÝÖÒ|Šsþ.!eÖÒó^ßðò›©Ä”ýú›swwvvè(3fdXŠY8ç´¡Ñ3¸u.omlÃ0„¿‚ã`6›PïQ)¥ÜjuT676—¦’©ÔÖŠEðú¼¥MbÊŒd*¹¾<Ö—9¡”€€s`=&àœƒR AQf.…¾¦Ó¡ CÉ×,( ßðNû]íB`‰ÇãÈd2àœCn3Ö…PÂ&XE˜L%棋¡…¶h4z€‹°p?×ý챆Ï ×[ðÿü®U’?áðÒ`ßÙþÞùùÀ€0PØs1ÍùC¾1 ¹˜0r¹‹ I×èŠËÊì-­bKIEND®B`‚ipe-7.1.4/src/ipe/icons/keyboard.png0000644000175000017500000000137212120621776017146 0ustar otfriedotfried‰PNG  IHDRÄ´l;sBIT|dˆ pHYs × ×B(›xtEXtSoftwarewww.inkscape.org›î<wIDAT8Ý•ÏKTQÇ¿çÜ{ß›÷Æ-\ˆN…h†!6BŠ‚Œ»B "ÿ‚¹ž6m¤MÐÂ­Š™¶}ÿB™A‘QAÑà8ΤÎÓ¹ó^ àÔ‘ /.œŸ{øÞsï%×uqâc¡þ3°çyt,àt:«â8ŽÜ£ýÏqBŸB–•Š. !Y¤TYE K´B] $€ ÁÑ‘±‡‡‚ •J™++…KRòYi˜uRˆzeµRÊ,3A ¦|ßÿlFT*úµ 5CC^ñPp%êéé9ņ5:“µúúîwl^* ¬ß°d²ýFss‹ª=Y‡²Ö˜™ýÓŒ€˜ADë‚.—ÐÖzËå`[U`fÔ7Ô³]»àív+ȲíTn1'&&ÆADˆÇ«QZ+a­¯b51¼š} hl<ƒÉד`"KÔœ¨v ·Š+ÅË;¦ÂqC4e[Öù©‡hiiùãØèø•D"±¶5nžç1€ý^³°R¸ëºÁVÇÇ¡ÿì9ŠþâmË;°îƒŠIEND®B`‚ipe-7.1.4/src/ipe/icons/mode_stretch.png0000644000175000017500000000160612120621776020026 0ustar otfriedotfried‰PNG  IHDRÄ´l;bKGDÿÿÿ ½§“ pHYs  šœtIMEÖíû¿ÜIDAT8˵•Oh\UÆß¹“‰Ö¢d&Æ1--]ˆ®\$ÅÜ„Œ]¥*±T •¶Ô*n Ä0‚ ÿ”±(¡ÆX…º° Ñ`ÑÖ(¢ ºP2XÉŸNRÑZ'“iŸ‹wß$“¾D©øàðþÜ{¿ûó}ç>øŸ.ev Ö›07~@Wœì¡\¹„3a&œ…X»_øðª[ôðÃÙŽŽŸá›ï‹?æ–$‚ A ´åòq÷d ÐØà¸ãö4ƒOl§/?AqúU%‘4 õ³ò~Ûýü;`3ñã/ ôå'éïfàð´åò±ìßÙNü‹ëŠ7:ØÀ¦–§/ðÕ×?1¼·“ìŽWy~g쉓ßѽýÎØ±}Ccõ®HªJúç%~†ö¾#¤nlB30…?й™ã'§0&«=Òuû†ÆH¬´S’†Ûrùà¡]´÷aräq¶íy›t:…IH!@áØ$·d›=`´!\,Wê] òR]J©TÛöŒrú­ÇX˜?‚š0'žz¸£è$lWÚ à矫÷¢‰tº‰{ž|‡Soîf~þ·@P86‰s¡çeËeúkqi}ÆË•‰L¦‰Î½c|yx¥ÒyLƇ:0Œ™ÙùÚ<Å5ÈZŒ£t›3)îÛÿ.ŸeîÜ…&™™+-— I”×buÔÖÖ˜)ñ`ç¦gÎÑsïf.U«<ûê§|v¨—»·¶pâõ^$!/œ´㳟ôGöíT‰l6ÃñSS´f›ùèt‘[[o¢ôg@×Á÷xù`—ïp.´œ³˜Î£6-,Uyq©f!§P ¦gKœx­w™™w„$åJµXž}hˆ9ói $…BÉè~ú}ÌSˆÊ`™»‚±€$p°a9!¸¹9«Î¯2|6­:„¢ôßpMc¹Ž-±gA¤|ì˜/…VˆØè_ß–Ëÿó¯iU“~ƒk}$}Ø*q>œ¿ ,øø]1”(œ_½«2Œ6¸ì¿U¥(þÃð5¢ EÖIEND®B`‚ipe-7.1.4/src/ipe/icons/mode_select.png0000644000175000017500000000105012120621776017622 0ustar otfriedotfried‰PNG  IHDRàw=øbKGDÿÿÿ ½§“ÝIDATxÚÕ–¿QÇ?ïŠ9½SãkÌ×x­9;:k +;;kÿþÿJj†@«„f+ dW~xc3¬°rûî®q“ÉfßËÎç}gfgþ÷ËlYÏ à&püÒç€Ý²—×ûà.°\:å̧€Ñhðx\? ä_à«€, ‚@{@ñ¼ \s€Ùl&ƒÁàB!€(Ф×ë]dX.—2ŸÏ%Žc™L&Òív½ §Ò1Y¹\¦Óé|Î’øÌòÀZK¥R¡Ýng‚X_çI%­V+ Ù ë>½C´«Õjr ¸¢>Íú×ê¥" CÂ0¤Z­ºí·ê¼°Þ~¼Xk±ÖÒh4œówÀkà ðS{•x•©ˆÈx<–z½.€A Q¹Rý¼žhˆ.gÍë Ðl63j€Äq,ý~ß­Ÿª\õ"µÀ+à% ÃáP¦Ó©Û{ìër>s¢”€§À3à8Þ¤¨8î¤%y ìj—ÔÁ àaŠŠçÀ#=”ñQ‘×Äõt Åq"|ŸTa) `2@Ò&Ý.p¸­ïÀ7`,“¥jÎØi Z5;º6UÛ˜Ùæó"—¨šßj?y½¾ë+t­«IEND®B`‚ipe-7.1.4/src/ipe/icons/ipe.png0000644000175000017500000000032312120621776016116 0ustar otfriedotfried‰PNG  IHDR TgÇPLTEÿÿÿÿÿÿÿ蜚tRNS@æØfoIDAT(‘µÏQ € Ð%ðtéõ¿Rsÿ«4I¤ã‡AÐâÏ>f]5ûZp°$ÐL4 ¬[Œàš8ô\àuºØc\ªH†X€ì)°¿ßà …!°¼VÞ΀ünfé§Ñx:ðwrÌ#sê-8ˆIEND®B`‚ipe-7.1.4/src/ipe/icons/fit_objects.png0000644000175000017500000000150212120621776017634 0ustar otfriedotfried‰PNG  IHDRÄ´l;bKGDÿÿÿ ½§“ pHYs  šœtIMEÖ 6be¿a5tEXtComment(c) 2004 Jakub Steiner Created with The GIMPÙ‹oŽIDAT8˵•MHTQÇçÌ+™´tB „VAX¤Aú‹ÚD-Zdb-’ Z´0F‡– -‚B°EŸfQ´©h+I  ÚeæGJÎ8Îkñî{óÆf¦vx÷{ß½ç¾ïƒÿDéí¾´­fß¹®ó'0ÀöjQ¤·Û°üª¶µÝÊPý¤§%‹‚ €Ms×£Œ­·}G¼¹fóEUž2| Hý»Jå«<æÿQIEND®B`‚ipe-7.1.4/src/ipe/icons/mode_math.png0000644000175000017500000000022412120621776017276 0ustar otfriedotfried‰PNG  IHDRÚ¹¯»PLTEÿ€€ªtRNS@æØfÇY >yåAe†¥†ªˆmÛ°m‹AкOì 1Áæà¸bs|?šÀá*E›Ã‚iÂÏøiËosRÁ”=nÇ6FøHe;ްÀ²L˜¦‰^¯‡n·»X1)3µÏ|Ù¢d˲bÀN§Ã×´Ûíd+ °lWÐÜV«ÅÂH‹~t¿U™f•Úe¥v@ÊHA Ã@³Ù„®ë,4þlÍd05yÜÇù² $ •4 %Ò’ÁAû>¦Ù!€ªëj28Üm²@ìvÔ¡P¨Œuýšöž ޶O(|ª ( ªú– žN§øOÐÉûÑ×ê·x|®­%în£©\>ÀéÙ ŽŽQÚ+¡XÜ¢l£P(@–7‘Ïç‘Ëe‘ÍfÙ5ÇŸeYæßEAq·ˆ½ý*•cön ìPÆk8@7u…èIEND®B`‚ipe-7.1.4/src/ipe/icons/mode_lines.png0000644000175000017500000000027112120621776017461 0ustar otfriedotfried‰PNG  IHDRàw=øbKGDÿÿÿ ½§“nIDATxÚí•1€ EÆs Ž\ÏÇÐñ"¸Ø„8Â_Úüå¥]4ŽHÁ–º\÷Ûh&Y\̸˜Õ/˜Z¿h–åÚ–º÷ÀÙ êòNd@d@z€h‰Å§`VÒB¬(© ùŸp4ò‘V'yƒ†,¢-·/:IEND®B`‚ipe-7.1.4/src/ipe/icons/undo.png0000644000175000017500000000176312120621776016317 0ustar otfriedotfried‰PNG  IHDRÄ´l;bKGDÿÿÿ ½§“ pHYs × ×B(›xtIMEÖ 8Ÿ?T€IDAT8Ë­”_h[UÇ¿çþÉM{›´©Í]ìŸté\u>Ì—"[…Õ¢¢ÈŠú2‘1Ê„>íQñEA¦>ŠŠ>8(¡/¡¢ Ä-[ctæaÓÉݬڤ’uÉBþÞäž{Žž[.Y¡xàǽ÷ÜŸó=ßßï Ã¸tnìd2Ž] i§K CG4óÏ3Øåv‚H™øä³ÏàoCgÆ{m×`e'¨ÅG *Ý~E2Þ°pôðSƒ‘ó×7ÔÄé÷šÕN`¹”ÓUÀó8¡Ø3ª#<F0l„úür¥˜/í}äAûÅð„úC"ÉJÁG^žœG݃ä=àPɤ(Úè=lxtßêÝ?Àï=žP¯%’l³-øÒÙ½Çuú×W“3ã¨Y#ˆYÑ\)6¬fz™ôUpx¡ûýÄ{«i{ô€z%‘dV+˜À— CG6˜4 ÀˆµÊò[¿Ü_|èi\ÿþÇŸëåBê¹yÌ··zœ»ÓD©´ŽñhCÓ¬£Zɬ@O×Ö~¬\[ºùÔI<¶cWÌÎe./- M_oÆŸ˜6P5O}óÝvr‰÷ d óÞ¾u‚F z<ÁQ`«sÏÎe.h`:uñ6"‘Èöüá ‡O€ÊÞcÅüÝ­zuÛÔ‡‹É=4wÔ ¹£FÇ2;—¹²V7žO]¼ (cî<éÕSwÏg äµõõ"´®^N­‰-Û"š"¨øfŽÇx嘇tuqi*äÖ-Æl›pØ/OYz? ®¤­ôß+¸ññYÜPu̵€ãñ}ýGÚxMZîçÉ]ÁÜ…€Õ½u1×AE,IEND®B`‚ipe-7.1.4/src/ipe/icons/mode_arc1.png0000644000175000017500000000037412120621776017201 0ustar otfriedotfried‰PNG  IHDRשÍÊ6PLTE?Bá?Bá?Báÿÿÿÿÿÿ?BáßBEÛx(tRNS?ŠÃéü¨>ÍXXŠ$øÁ£fIDAT(‘­ÉÀ Dq·Õ*þÿÏv9¨$ÐØ¤ï¤y8ŒP ŸRfEʈœÀNNÇÒ y‡Ü ”6Ö­`íÂùK‰Á»m¢Ö6Bî1^<73Œ LQ¯uÿ¤ówÖ„õ½áF(>½¯àIEND®B`‚ipe-7.1.4/src/ipe/icons/mode_arc2.png0000644000175000017500000000036512120621776017202 0ustar otfriedotfried‰PNG  IHDRשÍÊ3PLTE?Bá?Báÿÿÿÿÿÿ?BáßBØú'tRNS?ŠÃéü¨>ÍXŠX~ 3cIDAT(‘­YÀ q· êýOÛ%1@"­M:8ø|*€·]µvý€1uãõA+0Öyï¬&ÚIˆ)#æò’(¥Qȵ6÷´3õX÷_!Ê Á¿3'´¨ï­ê(&NÂ4UIEND®B`‚ipe-7.1.4/src/ipe/icons/mode_shredder.png0000644000175000017500000000042612120621776020151 0ustar otfriedotfried‰PNG  IHDRÄ´l;ÝIDATxÚcd `ö³ñŸÁéâYl ÿAtÚ/ìjÉãÔÄþËÌþɶC3ya óI£ŽCNȼKLPØ 8€n`1ÔȼJ¬ÁX GPC£Ì›@|–¨0F@ï£NÈPb æŸÀÊðAð7VƒMpJÈ`~ k? œúñ¦c"#¼tŒd€y(÷–ìä†%€ ý S!dÃq…7® k1 ½Ï€È]Bý¬ o¹`†2k0X3 BÙw±È1 É¿g &KSŒ [L|ÔpŽIEND®B`‚ipe-7.1.4/src/ipe/icons/mode_marks.png0000644000175000017500000000021412120621776017461 0ustar otfriedotfried‰PNG  IHDRÚ¹¯»PLTEÿ€€ªtRNS@æØf4IDAT™c`@ò @ÜüA¾I30@VÆÀÄü ¹ƒ ò€1£;“Dÿ ˜õ ðIEND®B`‚ipe-7.1.4/src/ipe/icons/mode_circle3.png0000644000175000017500000000066412120621776017701 0ustar otfriedotfried‰PNG  IHDRàw=øsRGB®ÎébKGDÿÿÿ ½§“ pHYs  šœtIMEÙ1%åï/4IDATHÇå•­RÃ@…¿2ÄÇÄFðAE="¡‡Øš[f{I²Hf˜áÌÄdwÏý;{þ2`”@%_)ÿ2×áSñðÜïBç@Z$‘±Åë·‘OÖ@„®E™t°£ ~šI§W¯”“‹N$j<ûÌÀ ªÒØ6èšy >EGU0âÚ vy%piIQ«E·¦)@¼c½P9äˆ1cÌ·`5øâ:Úì!祿ÊSŽm-ÚÕ- 2d»E í!@*\õ]ðñŸ„ÂÑê ù/äÚÂG NúÜû8©ºÀ´7»vYuÛ=˜K1®™(#PRôRœçgÀ5pœYwfS$ÑÍoÈßÂUlgtÞMY8IEND®B`‚ipe-7.1.4/src/ipe/icons/copy.png0000644000175000017500000000132512120621776016316 0ustar otfriedotfried‰PNG  IHDRÄ´l;bKGDˆŠ… ¥©Õ pHYs  šœtIMEÕ 3 –EZbIDAT8Ë••MOQ†ßsïL¿t×_Ðv¦þcˆ+W&.]³(Q0×&€•D‰!qíÆ­+C  ‘ $@k]ãXX"¦ÓÛÞãâ2Ó™ÚNÛÙ´é9óÜç¾÷£Tyµöµv1åCB4ž”>Žª[ªÓqž-,OËÅë7ëN\Ý‚­Ö33YQlWdfêt:rà7$I03O n6F ‡Gnnþä„ "3ÀËõ•a}Ž€‹ÅBðÝó<ùuçK~ñé13M¼¨D¨l¬ÎŽ4V]…[Sº¾nM•?iÜn·±WÝ™j§„cblŠJu"õz},ÔuKÃÁ…B†ÅƸ¶Ô\×µdæáÆÌŒf³€•R‘ÆF£1Úoa”Jwú`¿ÀÌÈçCÆž‡Úþ^ÐX*•FXš~"Š3633”êþgšOPÌ@2™Œ‚µÖ±ž×Æþ·jÐè8N`7hL$`YJ)h­ûà^¯™stë03ÎÎêA–á¾L&ƒl6 Èår+öa¾EÀŽSŒ†RJh­!„€?ûÛÅ3; N‘lÛX,Qض "aì,+X¼jmZkXv"ñãíÖ¦;êÜûƒ…m… ÐZãýö»a¯Yqÿ+k/–ó÷§ÏÌ&0fïÞ\^]àðû˜°e;ÿáümÛ‚”æcMÒ\×ç¿ÎqrzŒT&³Yž›ß VJ!•JEެ”}ë^Oãòê'§Ç€ Çå¹ùæÖŽy*«ŸºÝîƒÁ›«ˆ hªjð½åÅçýÚ?Æ” š}DWIEND®B`‚ipe-7.1.4/src/ipe/icons/pen.png0000644000175000017500000000016012120621776016122 0ustar otfriedotfried‰PNG  IHDRÚ¹¯»PLTEÿ€€ªtRNS@æØfIDAT™c`@òÿ °±ñq‰!‹CãÝÖéIEND®B`‚ipe-7.1.4/src/ipe/icons/snapbd.png0000644000175000017500000000022112120621776016605 0ustar otfriedotfried‰PNG  IHDRÕk PLTEÿ€€ÿÿÿÿvn÷³tRNS@æØf3IDAT™c` €IF0ÅÂs€Hj-Ëë? À)FˆD1 ÄÅ€l, Xkfó­IEND®B`‚ipe-7.1.4/src/ipe/icons/grid_visible.png0000644000175000017500000000027612120621776020012 0ustar otfriedotfried‰PNG  IHDRàw=ø…IDATxÚíTA€ [¿$ÿ~iƃ `7!bDân¤[»uäáÀê7có¨ôÌeMŒÖ…Üæ:x.¦‘6 >°F\™x‰¡†üÀUYw²=/ųkêYs5Õè­´L ¹EžuéÙÜðˆá€íSÿo:–@ר‹M¦_VôIEND®B`‚ipe-7.1.4/src/ipe/icons/fit_page.png0000644000175000017500000000077212120621776017127 0ustar otfriedotfried‰PNG  IHDRÄ´l;sBIT|dˆtEXtSoftwarewww.inkscape.org›î<ŒIDAT8­“ËjÂ@†Ï“XR¥¸³Ûú6- BQC}„Rè+¤W¤O`-Ú«BÉE]Kê%Õù»s1‰­†dæ›ïüÃ0zlßõÇ1i¥iÚëåÅUPëæûªÛû²¹Û|>û³)ÊfÜw%fnj @Dß÷Hp§ó¼ܲ¤7›ç± •¥7¤D:p2ˆ¡ RÓÆašæn`Ëj,=[än`!ÄÆd&æ œ`7ßDðzêv_bB 2 ƒ¼¬ýÿ|à`Ûõz-¢õíc+XJé‚¢!Q™{&÷zýØ‚U©T(öæ­ Ãˆ°Þfë=…`÷ÔW ü ™9•IûmƒAlåò™ïÆK_ëÕj5¢mŽ#¥qøÔàTàB¡ÛzR1³¬ªê[ûéáô_TþNDĨT:QŠÇÅ£ÑÇHŸL§úãè‹ÅB_.eNÊeNJ2ÊÌsf¶…¶â;“ÉØŠªL4Mäsy{8~ŽÇ_³_·cP¢IEND®B`‚ipe-7.1.4/src/ipe/icons/mode_label.png0000644000175000017500000000201012120621776017417 0ustar otfriedotfried‰PNG  IHDRÄ´l;sBIT|dˆtEXtSoftwarewww.inkscape.org›î<šIDAT8••ÁoUÇ?ß™íì0mhÃR‰à kÄ`ÐÀ‰F=yÐ`¢”Dh þ &&&šxÑ?€¤&r ÈOT)¡Û†=LÙîv»;;Ïyó¼Ìn¶Ð}É73¿—|?ó}óÞÌç;IÒ'’œïû[äyž ‚`aW¯sŽF«×®]{þàÁƒ£9çÆ®_¿žöz½—œsmç­ì•töСC{ggg¹yó&ÖZò<ÇZËáÇ9~üxåöíÛ_lç÷vI{åܹsµf³‰1f‹îß¿Ïììl|$iÛpÛ‚%ÍHzãĉ^£ÑÀC–e Œ1´Z-²,# Cxóÿ$~ÿôéÓ®ÓéÐív1ÆpïÞ½|aa!¦ÞØØ`ÿþý“¾ï_þÏàJ¥rõÔ©Sµ‡Ž–ßh4RcŒ{üøñhqSÅk’<,éõz½>3==M³Ù$Ë2’$ÁZ›_5›M3|˜µ–8Ž àƒg‚+•Êå3gÎDËËËdY†1†ÕÕÕžµökçÜw­VË ç1DQT“ôé®`I{%]8vì˜÷àÁŒ1¤iJ«Õò€œsKëëëcÈóœ0 ñû¾??›Jòéðq`N¬’±KHÓ4}çãvë-¶FÂÆlé+SD“‡ñK„KHÊ*—Ê V&o’®ÉÃzœ`r¹h Pv¢€›ßÇÑ@·¼e:Œllc ¾Å# –‡AXîw pY‰ßQØäûW("}Æ·QtÀe™ŠË¯®&cIwvÆÈ©ÕTWÒ‘Â¥ÂÒ8!—X©¸¾¸5áãõzÝ» Ç·]ÿ÷øºínWÕ>í/Ò¾¼!?(Å&u ©IEND®B`‚ipe-7.1.4/src/ipe/icons/mode_rotate.png0000644000175000017500000000153712120621776017653 0ustar otfriedotfried‰PNG  IHDRÄ´l;bKGDÿÿÿ ½§“ pHYs  šœtIMEÖ2Ž#ªìIDAT8Ëí”Ï‹GÇ?Õ;«;ãÙe‘¨6a%ÑdIè KæF&v/‚Ýþ só6·Ü¼Ìré9 9 sð⊺+YDè˜Å_`!ºjWuåÐU½5ãüò èîêªÏ{õ}ïüoÆ„ûQ©·õ‡nŒ-ñ¾ÿ…ɉÎ}Ÿû‚IB¿7À"7ÎheùÒ;ÁI"Ù|ø ­4pwzxnlýjg €jØ ý ½IðëD¡µÎqónæ’D¹Ë;Õ°û¸v­ƒð½g`×4wn¬°ÿì÷ÇÀwÂÊó°2ÑmÛ›k4šµ1}ÍZ)&dÉ¥V–W‰d¦4C±X¤X*æÐøÁSþøóiî`´²,ªaw,ˆjØe´²œå˜ •z{kòf{÷"„ÈÇ|eŽ~o˜—œDzµ³”Cm¤ ”€`'0S©·o5š5înlâ÷„O°0à ¸…Zð4°(ø®J½}½Ñ¬qk-Æó²µö™EmýbáàÜ5ÏÔ•^úA´¼ˆ­ýÞÅc¤”H•’$ ©R¤TH™¢TÊúïh4koíXPÀ–DV;KøA´lƃÖ|¿7䛯?CI‰T %3¸’*s(·×cnsƘø™f+õöF£YãÚh/Oà¶$ß.~nåØ<7§WÞ$ÔÖ£DO€RtÜŒ­ À?À_ÀK uO¾XøêüO¿øA¤­™ž?ާ³•z[›DNÇ€O€ÌØ„©Ý2P^\ºryºT>ï´lÙ$cÊ4ÎNUjޝÌHM1h@ÙvÞaFjÊO;õíÞ“Sùu·Ý`©ÍÅüÛgNýJZFIEND®B`‚ipe-7.1.4/src/ipe/icons/mode_circle1.png0000644000175000017500000000054212120621776017672 0ustar otfriedotfried‰PNG  IHDRàw=øbKGDÿÿÿ ½§“IDATxÚåÕ±NÂ`à„É…ÄÕ 5ñEð-pà Üœ˜|V'‡nlŽ&¾ƒ³&4F7G\~ÍŸJéãIºôÞ{ÎßÓÓ[þF˜¢À"\E¸7ªîÔ_á—x äÐÅ!†³Ae÷Ï­”SO£W×8ô—Ÿ(‹A»‚üçxkêog…-¸Ø„¤8;*sÜTö¦Ø²½Àñ…½’òî¼c'x(§È¶ë,pVÉžÓ(ŠßÒ’Ç.q\.,šÄ±Š«½ë5Çto‘Gk,š¯*ìä%ÇÝb¸aàúmÕÍä)+|‚ñÈÇa6 Éë:ôä›ÇvádYˆ_Å,ÔŠ[vöËüûø|‘XQO IEND®B`‚ipe-7.1.4/src/ipe/icons/shift_key.png0000644000175000017500000000063612120621776017335 0ustar otfriedotfried‰PNG  IHDRÄ´l;eIDATxÚcd `pƒ›ššøAt]]ÝG² ¶›õ˜åPšìtCa€Ã‰5´n£øM°ÀÙt !ÃÑ Ñ0ƒ‘ ]¤L¡ÊN7ù¿Œ!är ƒÑ] 53Ì Ž3ò@†vl]ñíØ¢{Ã}@´€óÊ-ÄΈÅ@Y õ ÙЗÛ|ØÙÙ@8m4›Á(Þ‡¹dèÏŸ?á4ºË‰5ø&,¢- tíK$9S¨Áê$»¦h°8ƒIs1’â§à°ƒZs±°Ó‚ °6(üˆ¿€âhðc‚©9§!ÌÈÈÈ é±Œ|ƒ‘ G6˜AÄy!²Áw ÊÉ7øã¾VVV.ÛÅ[ á 3˜ˆo c\AÁÅöš®a)!dƒ±¹CÉÅ@CO¢Ëã-†k)UH)éï÷)”2íkv-ŽÝŠB@¡kk¿±¬mâñ8JÉã‚eF±be僃7sç #zTð^4gEF¥aD1MËŠýâ|‘¶-‹p8ŒÊÜ]Ó4 …Ö™x=Áµ¦…òàlÙN;$‘ÍÍ-¹C-û’ #Zu;¶++n•ß{ì#žÔ*5nµ|á”-YÞŠ7³$F¯²ií¤<Ït«Ov¿Kõ¡¨•Tø@¹{…BÓ^¢”§DÛåþEù@lɪÆÀnSï«`pjç@ÂÈÈí* ¨êЉ@Ø6€ðØÌŒ±`pJü^a‡‹9&PkIEND®B`‚ipe-7.1.4/src/ipe/icons/snapvtx.png0000644000175000017500000000022612120621776017046 0ustar otfriedotfried‰PNG  IHDRÕk PLTEÿ€€ÿÿÿÿvn÷³tRNS@æØf8IDAT™c` p-SÜ)¨ ‹˜`S`Ša”PÈI–AªÅL±Bì`ÁïìÝÔ?\IEND®B`‚ipe-7.1.4/src/ipe/icons/mode_splines.png0000644000175000017500000000040212120621776020020 0ustar otfriedotfried‰PNG  IHDRàw=øbKGDÿÿÿ ½§“·IDATxÚc` ©iØ}'¹ÿÈ|Å}YˆQDŠ% {20000ŽÑYC¬; Ô"{2QŒÓ"Šc‘@Ø‹IE¥i*MÓob9HÊbºVdc: ¯—ÌÇ2‹fyƒùÈY‹®Ð[ƒ@/pýÎWÅpÒm¿.ÓŽç®ÔŽ%„¢¬lÓela;¯$ëEqÌDr’ÑŒ¢Ø ³;\/ÚÀk;2ÿ>>›Pcè‚IEND®B`‚ipe-7.1.4/src/ipe/icons/snapauto.png0000644000175000017500000000021312120621776017171 0ustar otfriedotfried‰PNG  IHDRÕk PLTEÿ€€ÿÿÿÿvn÷³tRNS@æØf-IDAT™c`Àx„Ú‡BAYpQ¡¡,`°PŒ9F°Jt*44»S"~LìbÙIEND®B`‚ipe-7.1.4/src/ipe/icons/mode_paragraph.png0000644000175000017500000000021712120621776020314 0ustar otfriedotfried‰PNG  IHDRÚ¹¯»PLTEÿ€€ªtRNS@æØf7IDAT™c`€V@`õÔ—20¨,…°Õ5$q+Ï}À ²§Ae=§ [¹÷üI«ýIEND®B`‚ipe-7.1.4/src/ipe/icons/redo.png0000644000175000017500000000145212120621776016276 0ustar otfriedotfried‰PNG  IHDRÄ´l;bKGDÿÿÿ ½§“ pHYs × ×B(›xtIMEÖ #K(‹O·IDAT8Ë­”MkQ†ßsç#­©­ý4ÖŠ"¢T V…‚X©(m•,Á•Èü—þê.ú fáG¡  Ŷ ±Ôkiš&˜‰ÍG373÷ºIÂd˜¤µxà0pÏá9ï¼sæÿ±¸.cqýàn} û‹íX\ïüïà+ç Ó ¾_Å»Âi?Ãxî‡n—Sh×úðéÝ"t™·öŽÅõIo&õþE÷òÀÙb[I­ÖÊeyžˆD"pj½ àýíñQZ]üÉZàrŒH%pÛS V²b@4­ÂæÁ‹àX\?`åú­Q”ei+Y“  ¦¤fÃÎIØyª|%\3 _\½tÚ&P(emBºõE—l¨ Á±EíÌí2 î@xJö†Ì¯BQº;`Ð(Yip±-– ‡ ‘Á@ƒÀШ ©èèi‡¶UÄÌìr]ýÚÔE¨-hm²Ç„¶ŽVl¥rfv9 àŒip2 N ÖÚ¬@ED’KŸ³.€»¦Á¿{ë¶[¨BAZaËœ[’ª t*Á¿ù·ÇÝØë/MVλ¹?¥4àé$+}TÀ ò¸ið„÷¬™b@RÊ/¿­… °¨9ã ÓàºO”ôe]±:™å7ñxzGét\.ÕR(;ùL»_«¾Ô*OÅÿF^5T)²ŸDñä –J¬ebÆ£"¹‘³Ve¼˜Uú½ÉÅ€–ߊ¯ƒcl.•´ôwXorïa?Ö>Š„V* ðÚ¡ø.£|eZ¬ŠÒK®:DŒr‘af‡{ÉÉþ’¶pj&ò™Ç–šï#”î¾sì1ôI[ ¯Üו¢G("ÒOj¨EŠu¹3?ç:Õ!°nAÙèŠõnCò:›cIEND®B`‚ipe-7.1.4/src/ipe/icons/mode_ink.png0000644000175000017500000000156512120621776017137 0ustar otfriedotfried‰PNG  IHDRÄ´l;sBIT|dˆtEXtSoftwarewww.inkscape.org›î<IDAT8­ÓQh[UÇñï¹9mn®ÉÒnY×.¦›–ÖuŒljWÚà‹dè˜2|ñžIœ2„1-C¾(lDPPqˆˆ¾ B‘áC#а­¬Ó5›m KšfIº„4·77÷ø’ÈV×´k=ð‡sçÿáÇá¡”b³#ÑÝÆ4AîÜ„ù!€ö? ^¿lÑÅI!x¹±¿)8Ñ·¿x4pÀïѪ¶Ã7›†£=\:¸¯·÷©'÷ºS%À…MÁшïí ~¢KN\¿m[“±¸™Ú0èpñ‘žÞÎcaC›LÞá¯Ù…2pþîsG#º~ tíê=²Ï+¯&渖“˜¥¼|¿aøÒè|6¼Ý]ÎL3mî`1›6Áù(7Ë‚£ýï–­/ ÷‡ŒöM.Í»(:òÙyÇQ|¼òüºàhDÃíñ¾¾§¯ç¡a’ßfÊÌÖ‚¨â­es>7ï¬ìký¼3§O¼…ª¾ßŠ%¹&ÈfÒüšßÎ΀Ÿ«SSYÛ¡'7Ki†W¿µç±þNÛ®ª‰?…uå;¶ú}L_›\ª,[Gbqóâýze³´†Ñúœ®»=‡ž~†R©$”7ÔKä¯|kÕlëëÕPX㎅tò·´´033ÃÒR…ŽÎ Òú;V7›õ® Ÿ={¦¥ö‡ÃûI§Ód2\RS¹Üí‚æö=‹›•fðêW![NjÕ4D"Aa1ïärÙ‚rªÃo¾›h†Þ–Rú‚Áà'»wïzåò—µäìsÉ)–óÊ©:õÎ͵PXñ*„Û:::~ðûýŒ“L&9úâó…®ŒŽŽþ½ôžÄB ü ¥…B´··ãñxRòÕ>+ ëFïI,„8÷ù|twwÓÖÖF¹\&•J±°°pøp»^UÀª×²RÊþ,„xø´±i†a`YÅb1 ¼˜Mª”•Rµaàð^}­ê©æ9` øXjõ”¤yõn°1þo4Bãh¼òIEND®B`‚ipe-7.1.4/src/ipe/icons/zoom_in.png0000644000175000017500000000060212120621776017013 0ustar otfriedotfried‰PNG  IHDRÄ´l;bKGDÿÿÿ ½§“ pHYs × ×B(›xtIMEÖ ,ôû+¼IDAT8Ëí•1KA„¿;OPl´¬,¬ìïJ‚þŒ4!… þI ±ñÛü[-,lr½…µ…Šâí s!1»Á Xd`afç=v†·°À¼…²V¤Ãc>¸jf¾;q`i·Ý Ón0V á™ñ?„57ñ5)ªçw)C“*£.Où2"Ç1o\P˜@ú‰ÕYï&õv ðúéxz~G3agÂΉ„ìl­†=wz·Sœ6÷É_¸»¨ÒɽÂUáÏZ}E“œ¨¶T¬¯-cšG܆fÕ%¼Tn¶7WØÛÝž5‰GØ•æ_§Fé/Ó-[¥˜->†`|ð^4lée'IEND®B`‚ipe-7.1.4/src/ipe/icons/snapint.png0000644000175000017500000000024312120621776017016 0ustar otfriedotfried‰PNG  IHDRÕk PLTEÿ€€ÿÿÿÿvn÷³tRNS@æØfEIDAT™c`@‚D900IF0 ,"‘g %ÁZÀŠ´€)ýX(¨D%TÔ¨™ öAm€;Rßjª­>AIEND®B`‚ipe-7.1.4/src/ipe/icons/snapangle.png0000644000175000017500000000026112120621776017312 0ustar otfriedotfried‰PNG  IHDRÕk PLTEÿ€€ÿÿÿÿvn÷³tRNS@æØfSIDAT™c`@ Œ ‚D9 F†U@QF†} IÅdddkqdS‚`ŠÕHˆ†AŒ—ƒ¨„êšâ1SbP’ a¶CÝÜT¹ƒ©lxIEND®B`‚ipe-7.1.4/src/ipe/icons/zoom_out.png0000644000175000017500000000037412120621776017222 0ustar otfriedotfried‰PNG  IHDRÄ´l;bKGDÿÿÿ ½§“ pHYs × ×B(›xtIMEÖ ;w(®{‰IDAT8Ëí’± a Fß6n`í w#8†­­#ˆ¸ÀaëºÀÝÖ¶"È]òY؈Æâïó ÍGx !$É_ÊwÐnN=ÐTz†þ¸n?ƒYÐÔ¶+FM¡IzWvÝùg‘HÌýi\o$p.0æ09˜‰É…;,ópp$öÝ¥úùUIRÁ Wb1ÛO“IEND®B`‚ipe-7.1.4/src/Makefile0000644000175000017500000000167312120621776014414 0ustar otfriedotfried# -------------------------------------------------------------------- # Makefile for building all components of Ipe # -------------------------------------------------------------------- GOAL ?= all subdirs = \ ipelib \ ipelets/lua \ ipelets/image \ ipetoipe \ ipe6upgrade \ ipeextract \ ipescript \ ipecairo \ iperender \ ipecanvas \ ipeview \ ipelua \ ipeui \ ipe .PHONY: all $(subdirs) all: $(subdirs) ipetoipe: ipelib ipelets/kgon: ipelib ipelets/image: ipelib ipelets/qvoronoi: ipelib ipe6upgrade: ipelib ipeextract: ipelib ipecairo: ipelib iperender: ipelib ipecairo ipecanvas: ipelib ipecairo ipeview: ipecanvas ipelua: ipelib ipescript: ipelib ipelua ipe: ipecanvas ipelua $(subdirs): $(MAKE) --directory=$@ $(GOAL) .PHONY: clean install clean: $(MAKE) GOAL=clean install: all $(MAKE) GOAL=install # -------------------------------------------------------------------- ipe-7.1.4/src/ipeview/0000755000175000017500000000000012120621776014415 5ustar otfriedotfriedipe-7.1.4/src/ipeview/ipeview.rc0000644000175000017500000000154212120621776016415 0ustar otfriedotfried#include #define IDI_MYICON 1 IDI_MYICON ICON DISCARDABLE "ipe.ico" VS_VERSION_INFO VERSIONINFO FILEVERSION 7,1,4,0 PRODUCTVERSION 7,1,4,0 FILEFLAGSMASK VS_FF_PRERELEASE FILEFLAGS VS_FF_PRERELEASE FILEOS VOS__WINDOWS32 FILETYPE VFT_APP FILESUBTYPE 0x0L BEGIN BLOCK "StringFileInfo" BEGIN BLOCK "040904B0" BEGIN VALUE "CompanyName", "Otfried Cheong\0" VALUE "FileDescription", "Ipe document viewer\0" VALUE "FileVersion", "7, 1, 4, 1\0" VALUE "InternalName", "Ipeview\0" VALUE "LegalCopyright", "Copyright (C) 2012\0" VALUE "LegalTrademarks", "\0" VALUE "OriginalFilename", "Ipeview.exe\0" VALUE "ProductName", "Ipe\0" VALUE "ProductVersion", "7, 1, 4, 1\0" END END END ipe-7.1.4/src/ipeview/Makefile0000644000175000017500000000224512120621776016060 0ustar otfriedotfried# -------------------------------------------------------------------- # Makefile for Ipeview # -------------------------------------------------------------------- OBJDIR = $(BUILDDIR)/obj/ipeview include ../common.mak TARGET = $(call exe_target,ipeview) CPPFLAGS += -I../include -I../ipecairo -I../ipecanvas \ $(UI_CFLAGS) $(CAIRO_CFLAGS) LIBS += -L$(buildlib) $(UI_LIBS) $(CAIRO_LIBS) -lipecanvas -lipecairo -lipe all: $(TARGET) win_sources = ipeview_win.cpp qt_sources = ipeview_qt.cpp moc_headers = ipeview_qt.h gtk_sources = ipeview_gtk.cpp ifdef WIN32 CXXFLAGS += -mwindows LDFLAGS += -mwindows resource = $(OBJDIR)/res.o $(resource): ipeview.rc $(WINDRES) -i ipeview.rc -o $@ --include-dir=../ipe else resource = endif $(TARGET): $(objects) $(resource) $(MAKE_BINDIR) $(CXX) $(LDFLAGS) -o $@ $^ $(LIBS) clean: @-rm -f $(objects) $(resource) $(TARGET) $(DEPEND) $(DEPEND): Makefile $(MAKE_DEPEND) -include $(DEPEND) install: $(TARGET) $(INSTALL_DIR) $(INSTALL_ROOT)$(IPEBINDIR) $(INSTALL_PROGRAMS) $(TARGET) $(INSTALL_ROOT)$(IPEBINDIR) # -------------------------------------------------------------------- ipe-7.1.4/src/ipeview/ipeview_win.cpp0000644000175000017500000002652612120621776017461 0ustar otfriedotfried// -------------------------------------------------------------------- // Ipeview with Windows UI // -------------------------------------------------------------------- /* This file is part of the extensible drawing editor Ipe. Copyright (C) 1993-2013 Otfried Cheong Ipe is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. As a special exception, you have permission to link Ipe with the CGAL library and distribute executables, as long as you follow the requirements of the Gnu General Public License in regard to all of the software in the executable aside from CGAL. Ipe 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 General Public License for more details. You should have received a copy of the GNU General Public License along with Ipe; if not, you can find it at "http://www.gnu.org/copyleft/gpl.html", or write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ #include "ipedoc.h" #include "ipecanvas_win.h" #include "ipetool.h" #include #include #define IDI_MYICON 1 using namespace ipe; // -------------------------------------------------------------------- class AppUi : public CanvasObserver { public: enum TAction { EOpen = 9001, EQuit, EGridVisible, EFullScreen, EFitPage, EZoomIn, EZoomOut, ENextView, EPreviousView, ENumActions = EPreviousView - 9000 }; static void init(HINSTANCE hInstance); AppUi(HINSTANCE hInstance); void show(int nCmdShow); bool load(const char* fn); void zoom(int delta); void nextView(int delta); void fitBox(const Rect &box); void updateLabel(); void cmd(int cmd); protected: // from CanvasObserver virtual void canvasObserverWheelMoved(int degrees); virtual void canvasObserverMouseAction(int button); private: void initUi(); ~AppUi(); static LRESULT CALLBACK wndProc(HWND hwnd, UINT Message, WPARAM wParam, LPARAM lParam); static const char className[]; HWND hwnd; Canvas *iCanvas; Snap iSnap; bool iGridVisible; Document *iDoc; String iFileName; int iPageNo; int iViewNo; }; const char AppUi::className[] = "ipeviewWindowClass"; AppUi::AppUi(HINSTANCE hInstance) { iCanvas = 0; iDoc = 0; iGridVisible = false; iPageNo = iViewNo = 0; iSnap.iSnap = Snap::ESnapGrid | Snap::ESnapVtx; iSnap.iGridVisible = false; iSnap.iGridSize = 8; iSnap.iAngleSize = M_PI / 6.0; iSnap.iSnapDistance = 10; iSnap.iWithAxes = false; iSnap.iOrigin = Vector::ZERO; iSnap.iDir = 0; HWND hwnd = CreateWindowEx(WS_EX_CLIENTEDGE, className, "Ipeview", WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, NULL, NULL, hInstance, this); if (hwnd == NULL) { MessageBox(NULL, "AppUi window creation failed!", "Error!", MB_ICONEXCLAMATION | MB_OK); exit(9); } assert(GetWindowLongPtr(hwnd, GWLP_USERDATA)); } void AppUi::initUi() { HMENU hMenu = CreateMenu(); HMENU hSubMenu = CreatePopupMenu(); AppendMenu(hSubMenu, MF_STRING, EOpen, "&Open\tCtrl+O"); AppendMenu(hSubMenu, MF_STRING, EQuit, "&Quit\tCtrl+Q"); AppendMenu(hMenu, MF_STRING | MF_POPUP, UINT(hSubMenu), "&File"); hSubMenu = CreatePopupMenu(); AppendMenu(hSubMenu, MF_STRING, EGridVisible, "&Grid visible\tF12"); AppendMenu(hSubMenu, MF_STRING, EFitPage, "&Fit page\tCtrl+F"); AppendMenu(hSubMenu, MF_STRING, EZoomIn, "Zoom &in\tCtrl++"); AppendMenu(hSubMenu, MF_STRING, EZoomOut, "Zoom &out\tCtrl+-"); AppendMenu(hMenu, MF_STRING | MF_POPUP, UINT(hSubMenu), "&View"); hSubMenu = CreatePopupMenu(); AppendMenu(hSubMenu, MF_STRING, ENextView, "&Next view\tPageDn"); AppendMenu(hSubMenu, MF_STRING, EPreviousView, "&Previous view\tPageUp"); AppendMenu(hMenu, MF_STRING | MF_POPUP, UINT(hSubMenu), "&Move"); SetMenu(hwnd, hMenu); iCanvas = new Canvas(hwnd); iCanvas->setSnap(iSnap); iCanvas->setObserver(this); // SetWindowPos(hwnd, HWND_NOTOPMOST, -20, -20, 1000, 800, SWP_SHOWWINDOW); } AppUi::~AppUi() { fprintf(stderr, "AppUi::~AppUi()\n"); } // -------------------------------------------------------------------- void AppUi::cmd(int cmd) { // ipeDebug("Command %d", cmd); switch (cmd) { case EOpen: { OPENFILENAME ofn; char szFileName[MAX_PATH] = ""; ZeroMemory(&ofn, sizeof(ofn)); ofn.lStructSize = sizeof(ofn); // SEE NOTE BELOW ofn.hwndOwner = hwnd; ofn.lpstrFilter = "Ipe Files\0*.ipe;*.pdf;*.eps\0All Files\0*.*\0"; ofn.lpstrFile = szFileName; ofn.nMaxFile = MAX_PATH; ofn.Flags = OFN_EXPLORER | OFN_FILEMUSTEXIST | OFN_HIDEREADONLY; ofn.lpstrDefExt = "ipe"; if (GetOpenFileName(&ofn)) load(szFileName); } break; case EQuit: PostMessage(hwnd, WM_CLOSE, 0, 0); break; case EGridVisible: { Snap snap = iCanvas->snap(); snap.iGridVisible = !snap.iGridVisible; iCanvas->setSnap(snap); CheckMenuItem(GetMenu(hwnd), EGridVisible, snap.iGridVisible ? MF_CHECKED : MF_UNCHECKED); iCanvas->update(); break; } case EFitPage: fitBox(iDoc->cascade()->findLayout()->paper()); break; case EZoomIn: zoom(+1); break; case EZoomOut: zoom(-1); break; case ENextView: nextView(+1); break; case EPreviousView: nextView(-1); break; default: // unknown action return; } } void AppUi::canvasObserverWheelMoved(int degrees) { if (degrees > 0) zoom(+1); else zoom(-1); } void AppUi::canvasObserverMouseAction(int button) { Tool *tool = new PanTool(iCanvas, iDoc->page(iPageNo), iViewNo); iCanvas->setTool(tool); } // -------------------------------------------------------------------- bool AppUi::load(const char *fname) { Document *doc = Document::loadWithErrorReport(fname); if (!doc) return false; iFileName = String(fname); doc->runLatex(); delete iDoc; iDoc = doc; iPageNo = 0; iViewNo = 0; /* if (iDoc->countPages() > 1) { int p = PageSelector::selectPageOrView(iDoc); if (p >= 0) iPageNo = p; if (iDoc->page(iPageNo)->countViews() > 1) { int v = PageSelector::selectPageOrView(iDoc, iPageNo); if (v >= 0) iViewNo = v; } } */ // iDoc->page(iPageNo)->setSelect(0, EPrimarySelected); iCanvas->setFontPool(iDoc->fontPool()); iCanvas->setPage(iDoc->page(iPageNo), iPageNo, iViewNo, iDoc->cascade()); iCanvas->setPan(Vector(300, 400)); iCanvas->update(); iCanvas->setFifiVisible(true); updateLabel(); return true; } // -------------------------------------------------------------------- void AppUi::updateLabel() { String s = iFileName; if (iFileName.rfind('/') >= 0) s = iFileName.substr(iFileName.rfind('/') + 1); if (iDoc->countTotalViews() > 1) { ipe::StringStream ss(s); ss << " (" << iPageNo + 1 << "-" << iViewNo + 1 << ")"; } SetWindowText(hwnd, s.z()); } void AppUi::fitBox(const Rect &box) { if (box.isEmpty()) return; double xfactor = box.width() > 0.0 ? (iCanvas->canvasWidth() / box.width()) : 20.0; double yfactor = box.height() > 0.0 ? (iCanvas->canvasHeight() / box.height()) : 20.0; double zoom = (xfactor > yfactor) ? yfactor : xfactor; iCanvas->setPan(0.5 * (box.bottomLeft() + box.topRight())); iCanvas->setZoom(zoom); iCanvas->update(); } void AppUi::zoom(int delta) { double zoom = iCanvas->zoom(); while (delta > 0) {zoom *= 1.3; --delta;} while (delta < 0) {zoom /= 1.3; ++delta;} iCanvas->setZoom(zoom); iCanvas->update(); } void AppUi::nextView(int delta) { const Page *page = iDoc->page(iPageNo); if (0 <= iViewNo + delta && iViewNo + delta < page->countViews()) { iViewNo += delta; } else if (0 <= iPageNo + delta && iPageNo + delta < iDoc->countPages()) { iPageNo += delta; if (delta > 0) iViewNo = 0; else iViewNo = iDoc->page(iPageNo)->countViews() - 1; } else // at beginning or end of sequence return; iCanvas->setPage(iDoc->page(iPageNo), iPageNo, iViewNo, iDoc->cascade()); iCanvas->update(); updateLabel(); } // -------------------------------------------------------------------- LRESULT CALLBACK AppUi::wndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) { AppUi *ui = (AppUi*) GetWindowLongPtr(hwnd, GWLP_USERDATA); switch (message) { case WM_CREATE: { LPCREATESTRUCT p = (LPCREATESTRUCT) lParam; ui = (AppUi *) p->lpCreateParams; ui->hwnd = hwnd; SetWindowLongPtr(hwnd, GWLP_USERDATA, (LONG_PTR) ui); ui->initUi(); } break; /* case WM_INITMENUPOPUP: if (ui && lParam == 1) { CheckMenuItem(EGridVisible); } break; */ case WM_COMMAND: if (ui) ui->cmd(LOWORD(wParam)); break; case WM_SIZE: if (ui && ui->iCanvas) { RECT rc; GetClientRect(hwnd, &rc); MoveWindow(ui->iCanvas->windowId(), 0, 0, rc.right, rc.bottom, TRUE); } break; case WM_CLOSE: DestroyWindow(hwnd); break; case WM_DESTROY: PostQuitMessage(0); delete ui; break; default: break; } return DefWindowProc(hwnd, message, wParam, lParam); } void AppUi::init(HINSTANCE hInstance) { WNDCLASSEX wc; wc.cbSize = sizeof(WNDCLASSEX); wc.style = 0; wc.lpfnWndProc = wndProc; wc.cbClsExtra = 0; wc.cbWndExtra = 0; wc.hInstance = hInstance; wc.hCursor = LoadCursor(NULL, IDC_ARROW); wc.hbrBackground = (HBRUSH)(COLOR_WINDOW+1); wc.lpszMenuName = NULL; wc.lpszClassName = className; wc.hIcon = LoadIcon(GetModuleHandle(NULL), MAKEINTRESOURCE(IDI_MYICON)); wc.hIconSm = HICON(LoadImage(GetModuleHandle(NULL), MAKEINTRESOURCE(IDI_MYICON), IMAGE_ICON, 16, 16, 0)); if (!RegisterClassEx(&wc)) { MessageBox(NULL, "AppUi registration failed!", "Error!", MB_ICONEXCLAMATION | MB_OK); exit(9); } } void AppUi::show(int nCmdShow) { ShowWindow(hwnd, nCmdShow); UpdateWindow(hwnd); } // -------------------------------------------------------------------- void usage() { MessageBox(NULL, "Ipeview needs to be called with a filename argument!", "Ipeview Error!", MB_ICONEXCLAMATION | MB_OK); exit(9); } int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow) { Platform::initLib(IPELIB_VERSION); AppUi::init(hInstance); ipe_init_canvas(hInstance); AppUi *ui = new AppUi(hInstance); if (strlen(lpCmdLine) == 0) usage(); if (!ui->load(lpCmdLine)) usage(); ui->show(nCmdShow); ACCEL accel[] = { { FVIRTKEY|FCONTROL, 'O', AppUi::EOpen }, { FVIRTKEY|FCONTROL, 'F', AppUi::EFitPage }, { FVIRTKEY|FCONTROL, 'Q', AppUi::EQuit }, { FVIRTKEY, VK_PRIOR, AppUi::EPreviousView }, { FVIRTKEY, VK_NEXT, AppUi::ENextView }, { FVIRTKEY|FCONTROL|FSHIFT, 0xbb, AppUi::EZoomIn }, { FVIRTKEY|FCONTROL, 0xbd, AppUi::EZoomOut }, { FVIRTKEY, VK_F12, AppUi::EGridVisible }, }; HACCEL hAccel = CreateAcceleratorTable(accel, sizeof(accel)/sizeof(ACCEL)); MSG msg; while (GetMessage(&msg, NULL, 0, 0) > 0) { if (!TranslateAccelerator(msg.hwnd, hAccel, &msg)) { TranslateMessage(&msg); DispatchMessage(&msg); } } return msg.wParam; } // -------------------------------------------------------------------- ipe-7.1.4/src/ipeview/ipeview_qt.h0000644000175000017500000000515012120621776016743 0ustar otfriedotfried// -*- C++ -*- // -------------------------------------------------------------------- // Ipeview for QT // -------------------------------------------------------------------- /* This file is part of the extensible drawing editor Ipe. Copyright (C) 1993-2013 Otfried Cheong Ipe is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. As a special exception, you have permission to link Ipe with the CGAL library and distribute executables, as long as you follow the requirements of the Gnu General Public License in regard to all of the software in the executable aside from CGAL. Ipe 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 General Public License for more details. You should have received a copy of the GNU General Public License along with Ipe; if not, you can find it at "http://www.gnu.org/copyleft/gpl.html", or write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ #ifndef IPEVIEW_H #define IPEVIEW_H #include "ipecanvas.h" #include #include using namespace ipe; // -------------------------------------------------------------------- class IpeAction : public QAction { Q_OBJECT public: IpeAction(int cmd, const QString &text, const char *shortcut, QObject *parent); signals: void triggered(int cmd); private slots: void forwardTrigger(); private: int iCommand; }; // -------------------------------------------------------------------- class AppUi : public QMainWindow, public CanvasObserver { Q_OBJECT public: enum TAction { EOpen, EQuit, EGridVisible, EFullScreen, EFitPage, EZoomIn, EZoomOut, ENextView, EPreviousView, ENumActions }; public: AppUi(Qt::WFlags f=0); void zoom(int delta); void nextView(int delta); void fitBox(const Rect &box); void updateLabel(); bool load(const char* fn); protected: // from CanvasObserver virtual void canvasObserverWheelMoved(int degrees); virtual void canvasObserverMouseAction(int button); public slots: void cmd(int cmd); private: Document *iDoc; CanvasBase *iCanvas; Snap iSnap; QMenu *iFileMenu; QMenu *iViewMenu; QMenu *iMoveMenu; IpeAction *iGridVisible; String iFileName; int iPageNo; int iViewNo; }; // -------------------------------------------------------------------- #endif ipe-7.1.4/src/ipeview/ipeview_qt.cpp0000644000175000017500000001662012120621776017302 0ustar otfriedotfried// -------------------------------------------------------------------- // Main function // -------------------------------------------------------------------- /* This file is part of the extensible drawing editor Ipe. Copyright (C) 1993-2013 Otfried Cheong Ipe is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. As a special exception, you have permission to link Ipe with the CGAL library and distribute executables, as long as you follow the requirements of the Gnu General Public License in regard to all of the software in the executable aside from CGAL. Ipe 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 General Public License for more details. You should have received a copy of the GNU General Public License along with Ipe; if not, you can find it at "http://www.gnu.org/copyleft/gpl.html", or write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ #include "ipeview_qt.h" #include "ipetool.h" #include "ipeselector_qt.h" #include "ipecanvas_qt.h" #include #include #include #include #include #include #include #include #include #include #include using namespace ipe; // -------------------------------------------------------------------- IpeAction::IpeAction(int cmd, const QString &text, const char *shortcut, QObject *parent) : QAction(text, parent) { iCommand = cmd; connect(this, SIGNAL(triggered()), SLOT(forwardTrigger())); connect(this, SIGNAL(triggered(int)), parent, SLOT(cmd(int))); if (shortcut) setShortcut(QKeySequence(shortcut)); } void IpeAction::forwardTrigger() { emit triggered(iCommand); } // -------------------------------------------------------------------- AppUi::AppUi(Qt::WFlags f) : QMainWindow(0, f) { iDoc = 0; iFileMenu = menuBar()->addMenu(tr("&File")); iViewMenu = menuBar()->addMenu(tr("&View")); iMoveMenu = menuBar()->addMenu(tr("&Move")); // iFileMenu->addAction(new IpeAction(EOpen, "Open", "Ctrl+O", this)); iFileMenu->addAction(new IpeAction(EQuit, "Quit", "Ctrl+Q", this)); iGridVisible = new IpeAction(EGridVisible, "Grid visible", "F12", this); iGridVisible->setCheckable(true); iViewMenu->addAction(iGridVisible); iViewMenu->addAction(new IpeAction(EFullScreen, "Full screen", "F11", this)); iViewMenu->addAction(new IpeAction(EFitPage, "Fit page", ".", this)); iViewMenu->addAction(new IpeAction(EZoomIn, "Zoom in", "=", this)); iViewMenu->addAction(new IpeAction(EZoomOut, "Zoom out", "-", this)); iMoveMenu->addAction(new IpeAction(ENextView, "Next view", "PgDown", this)); iMoveMenu->addAction(new IpeAction(EPreviousView, "Previous view", "PgUp", this)); Canvas *canvas = new Canvas(this); setCentralWidget(canvas); iCanvas = canvas; iCanvas->setObserver(this); Canvas::Style style = iCanvas->canvasStyle(); style.pretty = true; style.paperClip = true; iCanvas->setCanvasStyle(style); iSnap.iSnap = 0; // Snap::ESnapGrid; iSnap.iGridVisible = false; iSnap.iGridSize = 8; iSnap.iAngleSize = M_PI / 6.0; iSnap.iSnapDistance = 10; iSnap.iWithAxes = false; iSnap.iOrigin = Vector::ZERO; iSnap.iDir = 0; iCanvas->setSnap(iSnap); // iCanvas->setFifiVisible(true); } void AppUi::cmd(int cmd) { ipeDebug("Command %d", cmd); switch (cmd) { case EOpen: break; case EQuit: QApplication::exit(); break; case EGridVisible: { Snap snap = iCanvas->snap(); snap.iGridVisible = !snap.iGridVisible; iCanvas->setSnap(snap); iGridVisible->setChecked(snap.iGridVisible); iCanvas->update(); break; } case EFullScreen: { setWindowState(windowState() ^ Qt::WindowFullScreen); break; } case EFitPage: fitBox(iDoc->cascade()->findLayout()->paper()); break; case EZoomIn: zoom(+1); break; case EZoomOut: zoom(-1); break; case ENextView: nextView(+1); break; case EPreviousView: nextView(-1); break; default: // unknown action return; } } bool AppUi::load(const char *fname) { Document *doc = Document::loadWithErrorReport(fname); if (!doc) return false; iFileName = String(fname); doc->runLatex(); delete iDoc; iDoc = doc; iPageNo = 0; iViewNo = 0; if (iDoc->countPages() > 1) { int p = PageSelector::selectPageOrView(iDoc); if (p >= 0) iPageNo = p; if (iDoc->page(iPageNo)->countViews() > 1) { int v = PageSelector::selectPageOrView(iDoc, iPageNo); if (v >= 0) iViewNo = v; } } // iDoc->page(iPageNo)->setSelect(0, EPrimarySelected); iCanvas->setFontPool(iDoc->fontPool()); iCanvas->setPage(iDoc->page(iPageNo), iPageNo, iViewNo, iDoc->cascade()); iCanvas->setPan(Vector(300, 400)); iCanvas->update(); updateLabel(); return true; } void AppUi::updateLabel() { String s = iFileName; if (iFileName.rfind('/') >= 0) s = iFileName.substr(iFileName.rfind('/') + 1); if (iDoc->countTotalViews() > 1) { ipe::StringStream ss(s); ss << " (" << iPageNo + 1 << "-" << iViewNo + 1 << ")"; } setWindowTitle(QIpe(s)); } void AppUi::fitBox(const Rect &box) { if (box.isEmpty()) return; double xfactor = box.width() > 0.0 ? (iCanvas->canvasWidth() / box.width()) : 20.0; double yfactor = box.height() > 0.0 ? (iCanvas->canvasHeight() / box.height()) : 20.0; double zoom = (xfactor > yfactor) ? yfactor : xfactor; iCanvas->setPan(0.5 * (box.bottomLeft() + box.topRight())); iCanvas->setZoom(zoom); iCanvas->update(); } void AppUi::zoom(int delta) { double zoom = iCanvas->zoom(); while (delta > 0) {zoom *= 1.3; --delta;} while (delta < 0) {zoom /= 1.3; ++delta;} iCanvas->setZoom(zoom); iCanvas->update(); } void AppUi::canvasObserverWheelMoved(int degrees) { if (degrees > 0) zoom(+1); else zoom(-1); } void AppUi::canvasObserverMouseAction(int button) { Tool *tool = new PanTool(iCanvas, iDoc->page(iPageNo), iViewNo); iCanvas->setTool(tool); } void AppUi::nextView(int delta) { const Page *page = iDoc->page(iPageNo); if (0 <= iViewNo + delta && iViewNo + delta < page->countViews()) { iViewNo += delta; } else if (0 <= iPageNo + delta && iPageNo + delta < iDoc->countPages()) { iPageNo += delta; if (delta > 0) iViewNo = 0; else iViewNo = iDoc->page(iPageNo)->countViews() - 1; } else // at beginning or end of sequence return; iCanvas->setPage(iDoc->page(iPageNo), iPageNo, iViewNo, iDoc->cascade()); iCanvas->update(); updateLabel(); } // -------------------------------------------------------------------- static void usage() { fprintf(stderr, "Usage: ipeview \n"); exit(1); } int main(int argc, char *argv[]) { Platform::initLib(IPELIB_VERSION); QApplication a(argc, argv); setlocale(LC_NUMERIC, "C"); if (argc != 2) usage(); const char *load = argv[1]; AppUi *ui = new AppUi(); if (!ui->load(load)) exit(2); ui->show(); QObject::connect(&a, SIGNAL(lastWindowClosed()), &a, SLOT(quit())); return a.exec(); } // -------------------------------------------------------------------- ipe-7.1.4/src/ipeview/ipeview_gtk.cpp0000644000175000017500000002251212120621776017440 0ustar otfriedotfried// -------------------------------------------------------------------- // Ipeview for GTK // -------------------------------------------------------------------- /* This file is part of the extensible drawing editor Ipe. Copyright (C) 1993-2013 Otfried Cheong Ipe is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. As a special exception, you have permission to link Ipe with the CGAL library and distribute executables, as long as you follow the requirements of the Gnu General Public License in regard to all of the software in the executable aside from CGAL. Ipe 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 General Public License for more details. You should have received a copy of the GNU General Public License along with Ipe; if not, you can find it at "http://www.gnu.org/copyleft/gpl.html", or write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ #include "ipedoc.h" #include "ipecanvas_gtk.h" #include "ipetool.h" #include using namespace ipe; class AppUi : public CanvasObserver { public: enum TAction { EOpen = 9001, EQuit, EGridVisible, EFullScreen, EFitPage, EZoomIn, EZoomOut, ENextView, EPreviousView, ENumActions = EPreviousView - 9000 }; AppUi(); virtual ~AppUi(); void show(); bool load(const char* fn); void zoom(int delta); void nextView(int delta); void fitBox(const Rect &box); void updateLabel(); void cmd(int action); GtkWidget *windowId() const { return iWindow; } protected: // from CanvasObserver virtual void canvasObserverWheelMoved(int degrees); virtual void canvasObserverMouseAction(int button); private: void addItem(int m, int action, const char *label, const char *shortcut = 0, bool checkable=false); CanvasBase *iCanvas; Snap iSnap; bool iGridVisible; Document *iDoc; String iFileName; int iPageNo; int iViewNo; GtkWidget *iWindow; GtkWidget *iRootMenu[3]; GtkWidget *iSubMenu[3]; GtkWidget *vbox; GtkAccelGroup *iAccelGroup; }; static void menuitem_response(GtkWidget *item, AppUi::TAction a) { AppUi *ui = (AppUi *) g_object_get_data(G_OBJECT(item), "appui"); ui->cmd(a); } void AppUi::addItem(int m, int action, const char *label, const char *shortcut, bool checkable) { GtkMenuShell *menu = GTK_MENU_SHELL(iSubMenu[m]); GtkWidget *item = checkable ? gtk_check_menu_item_new_with_label(label) : gtk_menu_item_new_with_label(label); g_object_set_data(G_OBJECT(item), "appui", this); gtk_menu_shell_append(menu, item); g_signal_connect(item, "activate", G_CALLBACK(menuitem_response), GINT_TO_POINTER(action)); if (shortcut) { guint accel_key; GdkModifierType accel_mods; gtk_accelerator_parse(shortcut, &accel_key, &accel_mods); if (accel_key > 0) gtk_widget_add_accelerator(item, "activate", iAccelGroup, accel_key, accel_mods, GTK_ACCEL_VISIBLE); } gtk_widget_show(item); /* gtk_accel_group_connect(iAccelGroup, accel_key, accel_mods, GtkAccelFlags(0), g_cclosure_new(G_CALLBACK(shortcutResponse), this, NULL)); */ } AppUi::AppUi() { iWindow = gtk_window_new(GTK_WINDOW_TOPLEVEL); gtk_widget_set_size_request (GTK_WIDGET(iWindow), 600, 400); gtk_window_set_title(GTK_WINDOW(iWindow), "Ipeview"); g_signal_connect(iWindow, "delete-event", G_CALLBACK(gtk_main_quit), NULL); iAccelGroup = gtk_accel_group_new(); gtk_window_add_accel_group(GTK_WINDOW(iWindow), iAccelGroup); for (int i = 0; i < 3; ++i) iSubMenu[i] = gtk_menu_new(); addItem(0, EOpen, "Open", "O"); addItem(0, EQuit, "Quit", "Q"); addItem(1, EGridVisible, "Grid visible", "F12", true); addItem(1, EFullScreen, "Full screen", 0, true); addItem(1, EFitPage, "Fit page", "F"); addItem(1, EZoomIn, "Zoom in", "plus"); addItem(1, EZoomOut, "Zoom out", "minus"); addItem(2, ENextView, "Next view", "Next"); addItem(2, EPreviousView, "Previous view", "Prior"); iRootMenu[0] = gtk_menu_item_new_with_mnemonic("_File"); iRootMenu[1] = gtk_menu_item_new_with_mnemonic("_View"); iRootMenu[2] = gtk_menu_item_new_with_mnemonic("_Move"); vbox = gtk_vbox_new(FALSE, 0); gtk_container_add(GTK_CONTAINER(iWindow), vbox); gtk_widget_show(vbox); GtkWidget *menu_bar = gtk_menu_bar_new(); gtk_box_pack_start(GTK_BOX (vbox), menu_bar, FALSE, FALSE, 2); gtk_widget_show(menu_bar); for (int i = 0; i < 3; ++i) { gtk_widget_show(iRootMenu[i]); gtk_menu_item_set_submenu(GTK_MENU_ITEM(iRootMenu[i]), iSubMenu[i]); gtk_menu_shell_append(GTK_MENU_SHELL(menu_bar), iRootMenu[i]); } Canvas *canvas = new Canvas(iWindow); gtk_box_pack_end(GTK_BOX(vbox), canvas->window(), TRUE, TRUE, 2); gtk_widget_show(canvas->window()); iDoc = 0; iGridVisible = false; iPageNo = iViewNo = 0; iSnap.iSnap = Snap::ESnapGrid | Snap::ESnapVtx; iSnap.iGridVisible = false; iSnap.iGridSize = 8; iSnap.iAngleSize = M_PI / 6.0; iSnap.iSnapDistance = 10; iSnap.iWithAxes = false; iSnap.iOrigin = Vector::ZERO; iSnap.iDir = 0; iCanvas = canvas; iCanvas->setObserver(this); iCanvas->setSnap(iSnap); iCanvas->setFifiVisible(true); } AppUi::~AppUi() { fprintf(stderr, "AppUi::~AppUi()\n"); } void AppUi::show() { gtk_widget_show(iWindow); } // -------------------------------------------------------------------- void AppUi::cmd(int cmd) { ipeDebug("Command %d", cmd); switch (cmd) { case EOpen: // load(szFileName); break; case EQuit: gtk_main_quit(); break; case EFullScreen: gtk_window_fullscreen(GTK_WINDOW(iWindow)); break; case EGridVisible: { Snap snap = iCanvas->snap(); snap.iGridVisible = !snap.iGridVisible; iCanvas->setSnap(snap); iCanvas->update(); break; } case EFitPage: fitBox(iDoc->cascade()->findLayout()->paper()); break; case EZoomIn: zoom(+1); break; case EZoomOut: zoom(-1); break; case ENextView: nextView(+1); break; case EPreviousView: nextView(-1); break; default: // unknown action return; } } void AppUi::canvasObserverWheelMoved(int degrees) { if (degrees > 0) zoom(+1); else zoom(-1); } void AppUi::canvasObserverMouseAction(int button) { Tool *tool = new PanTool(iCanvas, iDoc->page(iPageNo), iViewNo); iCanvas->setTool(tool); } // -------------------------------------------------------------------- bool AppUi::load(const char *fname) { Document *doc = Document::loadWithErrorReport(fname); if (!doc) return false; iFileName = String(fname); doc->runLatex(); delete iDoc; iDoc = doc; iPageNo = 0; iViewNo = 0; /* if (iDoc->countPages() > 1) { int p = PageSelector::selectPageOrView(iDoc); if (p >= 0) iPageNo = p; if (iDoc->page(iPageNo)->countViews() > 1) { int v = PageSelector::selectPageOrView(iDoc, iPageNo); if (v >= 0) iViewNo = v; } } */ iDoc->page(iPageNo)->setSelect(0, EPrimarySelected); iCanvas->setFontPool(iDoc->fontPool()); iCanvas->setPage(iDoc->page(iPageNo), iPageNo, iViewNo, iDoc->cascade()); iCanvas->setPan(Vector(300, 400)); iCanvas->update(); iCanvas->setFifiVisible(true); updateLabel(); return true; } // -------------------------------------------------------------------- void AppUi::updateLabel() { String s = iFileName; if (iFileName.rfind('/') >= 0) s = iFileName.substr(iFileName.rfind('/') + 1); if (iDoc->countTotalViews() > 1) { ipe::StringStream ss(s); ss << " (" << iPageNo + 1 << "-" << iViewNo + 1 << ")"; } gtk_window_set_title(GTK_WINDOW(iWindow), s.z()); } void AppUi::fitBox(const Rect &box) { if (box.isEmpty()) return; double xfactor = box.width() > 0.0 ? (iCanvas->canvasWidth() / box.width()) : 20.0; double yfactor = box.height() > 0.0 ? (iCanvas->canvasHeight() / box.height()) : 20.0; double zoom = (xfactor > yfactor) ? yfactor : xfactor; iCanvas->setPan(0.5 * (box.bottomLeft() + box.topRight())); iCanvas->setZoom(zoom); iCanvas->update(); } void AppUi::zoom(int delta) { double zoom = iCanvas->zoom(); while (delta > 0) {zoom *= 1.3; --delta;} while (delta < 0) {zoom /= 1.3; ++delta;} iCanvas->setZoom(zoom); iCanvas->update(); } void AppUi::nextView(int delta) { const Page *page = iDoc->page(iPageNo); if (0 <= iViewNo + delta && iViewNo + delta < page->countViews()) { iViewNo += delta; } else if (0 <= iPageNo + delta && iPageNo + delta < iDoc->countPages()) { iPageNo += delta; if (delta > 0) iViewNo = 0; else iViewNo = iDoc->page(iPageNo)->countViews() - 1; } else // at beginning or end of sequence return; iCanvas->setPage(iDoc->page(iPageNo), iPageNo, iViewNo, iDoc->cascade()); iCanvas->update(); updateLabel(); } // -------------------------------------------------------------------- int main(int argc, char *argv[]) { Platform::initLib(IPELIB_VERSION); gtk_init(&argc, &argv); AppUi *ui = new AppUi(); if (argc > 1 && !ui->load(argv[1])) exit(2); ui->show(); gtk_main(); delete ui; return 0; } // -------------------------------------------------------------------- ipe-7.1.4/src/ipeui/0000755000175000017500000000000012120621776014060 5ustar otfriedotfriedipe-7.1.4/src/ipeui/ipeui_qt.cpp0000644000175000017500000005611112120621776016407 0ustar otfriedotfried// -------------------------------------------------------------------- // Lua bindings for Qt dialogs // -------------------------------------------------------------------- /* This file is part of the extensible drawing editor Ipe. Copyright (C) 1993-2013 Otfried Cheong Ipe is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. As a special exception, you have permission to link Ipe with the CGAL library and distribute executables, as long as you follow the requirements of the Gnu General Public License in regard to all of the software in the executable aside from CGAL. Ipe 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 General Public License for more details. You should have received a copy of the GNU General Public License along with Ipe; if not, you can find it at "http://www.gnu.org/copyleft/gpl.html", or write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ #include "ipeui_qt.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #if defined(WIN32) #include #endif // -------------------------------------------------------------------- inline void push_string(lua_State *L, const QString &str) { lua_pushstring(L, str.toUtf8()); } inline QString tostring(lua_State *L, int i) { return QString::fromUtf8(lua_tostring(L, i)); } inline QString checkstring(lua_State *L, int i) { return QString::fromUtf8(luaL_checkstring(L, i)); } // -------------------------------------------------------------------- class XmlHighlighter : public QSyntaxHighlighter { public: XmlHighlighter(QTextEdit *textEdit); protected: void applyFormat(const QString &text, QRegExp &exp, const QTextCharFormat &format); virtual void highlightBlock(const QString &text); }; void XmlHighlighter::applyFormat(const QString &text, QRegExp &exp, const QTextCharFormat &format) { int index = text.indexOf(exp); while (index >= 0) { int length = exp.matchedLength(); setFormat(index, length, format); index = text.indexOf(exp, index + length); } } void XmlHighlighter::highlightBlock(const QString &text) { QTextCharFormat tagFormat, stringFormat, numberFormat; tagFormat.setFontWeight(QFont::Bold); tagFormat.setForeground(Qt::blue); stringFormat.setForeground(Qt::darkMagenta); numberFormat.setForeground(Qt::red); QRegExp tagExp( "<.*>" ); QRegExp stringExp( "\"[a-zA-Z]*\"" ); QRegExp numberExp( "[+|-]*[0-9]*.[0-9][0-9]*" ); applyFormat(text, tagExp, tagFormat); applyFormat(text, stringExp, stringFormat); applyFormat(text, numberExp, numberFormat); } XmlHighlighter::XmlHighlighter(QTextEdit *textEdit) : QSyntaxHighlighter(textEdit) { // nothing } // -------------------------------------------------------------------- class LatexHighlighter : public QSyntaxHighlighter { public: LatexHighlighter(QTextEdit *textEdit); protected: void applyFormat(const QString &text, QRegExp &exp, const QTextCharFormat &format); virtual void highlightBlock(const QString &text); }; void LatexHighlighter::applyFormat(const QString &text, QRegExp &exp, const QTextCharFormat &format) { int index = text.indexOf(exp); while (index >= 0) { int length = exp.matchedLength(); setFormat(index, length, format); index = text.indexOf(exp, index + length); } } void LatexHighlighter::highlightBlock(const QString &text) { QTextCharFormat mathFormat, tagFormat; mathFormat.setForeground(Qt::red); tagFormat.setFontWeight(QFont::Bold); tagFormat.setForeground(Qt::blue); QRegExp mathExp( "\\$[^$]+\\$" ); QRegExp tagExp( "\\\\[a-zA-Z]+" ); applyFormat(text, mathExp, mathFormat); applyFormat(text, tagExp, tagFormat); } LatexHighlighter::LatexHighlighter(QTextEdit *textEdit) : QSyntaxHighlighter(textEdit) { // nothing } // -------------------------------------------------------------------- PDialog::PDialog(lua_State *L0, WINID parent, const char *caption) : QDialog(parent), Dialog(L0, parent, caption) { setWindowTitle(caption); QVBoxLayout *vlo = new QVBoxLayout; setLayout(vlo); iGrid = new QGridLayout; vlo->addLayout(iGrid); iButtonArea = new QHBoxLayout; vlo->addLayout(iButtonArea); iButtonArea->addStretch(1); QShortcut *shortcut = new QShortcut(QKeySequence("Ctrl+Return"), this); connect(shortcut, SIGNAL(activated()), SLOT(accept())); } PDialog::~PDialog() { // } void PDialog::keyPressEvent(QKeyEvent *e) { if (iIgnoreEscape && e->key() == Qt::Key_Escape) return; QDialog::keyPressEvent(e); } void PDialog::notifyLua() { QObject *s = sender(); for (uint i = 0; i < iWidgets.size(); ++i) { if (s == iWidgets[i]) { callLua(iElements[i].lua_method); return; } } } static void markupLog(QTextEdit *t, const QString &text) { QTextDocument *doc = new QTextDocument(t); doc->setPlainText(text); QTextCursor cursor(doc); int curPos = 0; int errNo = 0; for (;;) { int nextErr = text.indexOf(QLatin1String("\n!"), curPos); if (nextErr < 0) break; int lines = 0; while (curPos < nextErr + 1) { if (text[curPos++] == QLatin1Char('\n')) ++lines; } cursor.movePosition(QTextCursor::Down, QTextCursor::MoveAnchor, lines); int pos = cursor.position(); cursor.movePosition(QTextCursor::Down); cursor.setPosition(pos, QTextCursor::KeepAnchor); ++errNo; QString s; s.sprintf("err%d", errNo); QTextCharFormat format; format.setBackground(Qt::yellow); format.setAnchorName(s); format.setAnchor(true); cursor.setCharFormat(format); } t->setDocument(doc); t->scrollToAnchor(QLatin1String("err1")); } void PDialog::setMapped(lua_State *L, int idx) { SElement &m = iElements[idx]; QWidget *w = iWidgets[idx]; switch (m.type) { case ELabel: (qobject_cast(w))->setText(QString::fromUtf8(m.text.z())); break; case ECheckBox: (qobject_cast(w))->setChecked(m.value); break; case ETextEdit: (qobject_cast(w))->setText(QString::fromUtf8(m.text.z())); break; case EInput: (qobject_cast(w))->setText(QString::fromUtf8(m.text.z())); break; case EList: { QListWidget *l = qobject_cast(w); if (!lua_isnumber(L, 3)) { l->clear(); for (int k = 0; k < int(m.items.size()); ++k) l->addItem(QString::fromUtf8(m.items[k].z())); } l->setCurrentRow(m.value); } break; case ECombo: { QComboBox *b = qobject_cast(w); if (!lua_isnumber(L, 3)) { b->clear(); for (int k = 0; k < int(m.items.size()); ++k) b->addItem(QString::fromUtf8(m.items[k].z())); } b->setCurrentIndex(m.value); } break; default: break; // EButton } } bool PDialog::buildAndRun(int w, int h) { for (int i = 0; i < int(iElements.size()); ++i) { SElement &m = iElements[i]; if (m.row < 0) { QPushButton *b = new QPushButton(QString::fromUtf8(m.text.z()), this); iWidgets.push_back(b); if (m.flags & EAccept) { b->setDefault(true); connect(b, SIGNAL(clicked()), SLOT(accept())); } else if (m.flags & EReject) connect(b, SIGNAL(clicked()), SLOT(reject())); else if (m.lua_method != LUA_NOREF) connect(b, SIGNAL(clicked()), SLOT(notifyLua())); iButtonArea->addWidget(b); } else { QWidget *w = 0; switch (m.type) { case ELabel: w = new QLabel(QString::fromUtf8(m.text.z()), this); break; case EButton: { QPushButton *b = new QPushButton(QString::fromUtf8(m.text.z()), this); if (m.flags & EAccept) connect(b, SIGNAL(clicked()), SLOT(accept())); else if (m.flags & EReject) connect(b, SIGNAL(clicked()), SLOT(reject())); else if (m.lua_method != LUA_NOREF) connect(b, SIGNAL(clicked()), SLOT(notifyLua())); w = b; } break; case ECheckBox: { QCheckBox *ch = new QCheckBox(QString::fromUtf8(m.text.z()), this); if (m.lua_method != LUA_NOREF) connect(ch, SIGNAL(stateChanged(int)), SLOT(notifyLua())); ch->setChecked(m.value); w = ch; } break; case EInput: { QLineEdit *e = new QLineEdit(this); e->setText(QString::fromUtf8(m.text.z())); w = e; } break; case ETextEdit: { QTextEdit *t = new QTextEdit(this); t->setAcceptRichText(false); if (m.flags & EReadOnly) t->setReadOnly(true); if (m.flags & EXml) (void) new XmlHighlighter(t); else if (m.flags & ELatex) (void) new LatexHighlighter(t); QString text = QString::fromUtf8(m.text.z()); if (m.flags & ELogFile) { markupLog(t, text); } else t->setPlainText(text); w = t; } break; case ECombo: { QComboBox *b = new QComboBox(this); for (int k = 0; k < int(m.items.size()); ++k) b->addItem(QString::fromUtf8(m.items[k].z())); b->setCurrentIndex(m.value); w = b; } break; case EList: { QListWidget *l = new QListWidget(this); for (int k = 0; k < int(m.items.size()); ++k) l->addItem(QString::fromUtf8(m.items[k].z())); w = l; } break; default: break; } iWidgets.push_back(w); gridlayout()->addWidget(w, m.row, m.col, m.rowspan, m.colspan); } } int result = exec(); retrieveValues(); // for future reference return (result == QDialog::Accepted); } void PDialog::retrieveValues() { for (int i = 0; i < int(iElements.size()); ++i) { SElement &m = iElements[i]; QWidget *w = iWidgets[i]; switch (m.type) { case EInput: m.text = String((qobject_cast(w))->text().toUtf8()); break; case ETextEdit: m.text = String((qobject_cast(w))->toPlainText().toUtf8()); break; case EList: { int r = (qobject_cast(w))->currentRow(); m.value = (r >= 0) ? r : 0; } break; case ECombo: m.value = (qobject_cast(w))->currentIndex(); break; case ECheckBox: m.value = qobject_cast(w)->isChecked(); break; default: break; // label and button - nothing to do } } } void PDialog::enableItem(int idx, bool value) { iWidgets[idx]->setEnabled(value); } // -------------------------------------------------------------------- static int dialog_constructor(lua_State *L) { QWidget *parent = check_winid(L, 1); const char *s = luaL_checkstring(L, 2); Dialog **dlg = (Dialog **) lua_newuserdata(L, sizeof(Dialog *)); *dlg = 0; luaL_getmetatable(L, "Ipe.dialog"); lua_setmetatable(L, -2); *dlg = new PDialog(L, parent, s); return 1; } // -------------------------------------------------------------------- MenuAction::MenuAction(const QString &name, int number, const QString &item, const QString &text, QWidget *parent) : QAction(text, parent) { iName = name; iItemName = item; iNumber = number; } // -------------------------------------------------------------------- PMenu::PMenu(WINID parent) { iMenu = new QMenu(); } PMenu::~PMenu() { delete iMenu; } int PMenu::execute(lua_State *L) { int vx = luaL_checkint(L, 2); int vy = luaL_checkint(L, 3); QAction *a = iMenu->exec(QPoint(vx, vy)); MenuAction *ma = qobject_cast(a); if (ma) { push_string(L, ma->name()); lua_pushnumber(L, ma->number()); push_string(L, ma->itemName()); return 3; } return 0; } #define SIZE 16 static QIcon colorIcon(double red, double green, double blue) { QPixmap pixmap(SIZE, SIZE); pixmap.fill(QColor(int(red * 255.0 + 0.5), int(green * 255.0 + 0.5), int(blue * 255.0 + 0.5))); return QIcon(pixmap); } int PMenu::add(lua_State *L) { QString name = checkstring(L, 2); QString title = checkstring(L, 3); if (lua_gettop(L) == 3) { iMenu->addAction(new MenuAction(name, 0, QString(), title, iMenu)); } else { luaL_argcheck(L, lua_istable(L, 4), 4, "argument is not a table"); bool hasmap = !lua_isnoneornil(L, 5) && lua_isfunction(L, 5); bool hastable = !hasmap && !lua_isnoneornil(L, 5); bool hascolor = !lua_isnoneornil(L, 6) && lua_isfunction(L, 6); bool hascheck = !hascolor && !lua_isnoneornil(L, 6); if (hastable) luaL_argcheck(L, lua_istable(L, 5), 5, "argument is not a function or table"); QString current; if (hascheck) { luaL_argcheck(L, lua_isstring(L, 6), 6, "argument is not a function or string"); current = checkstring(L, 6); } int no = lua_rawlen(L, 4); QMenu *sm = new QMenu(title, iMenu); for (int i = 1; i <= no; ++i) { lua_rawgeti(L, 4, i); luaL_argcheck(L, lua_isstring(L, -1), 4, "items must be strings"); QString item = tostring(L, -1); QString text = item; if (hastable) { lua_rawgeti(L, 5, i); luaL_argcheck(L, lua_isstring(L, -1), 5, "labels must be strings"); text = tostring(L, -1); lua_pop(L, 1); } if (hasmap) { lua_pushvalue(L, 5); // function lua_pushnumber(L, i); // index lua_pushvalue(L, -3); // name lua_call(L, 2, 1); // function returns label luaL_argcheck(L, lua_isstring(L, -1), 5, "function does not return string"); text = tostring(L, -1); lua_pop(L, 1); // pop result } MenuAction *ma = new MenuAction(name, i, item, text, sm); if (hascolor) { lua_pushvalue(L, 6); // function lua_pushnumber(L, i); // index lua_pushvalue(L, -3); // name lua_call(L, 2, 3); // function returns red, green, blue double red = luaL_checknumber(L, -3); double green = luaL_checknumber(L, -2); double blue = luaL_checknumber(L, -1); lua_pop(L, 3); // pop result QIcon icon = colorIcon(red, green, blue); ma->setIcon(icon); ma->setIconVisibleInMenu(true); } if (hascheck) { ma->setCheckable(true); ma->setChecked(item == current); } lua_pop(L, 1); // item sm->addAction(ma); } iMenu->addMenu(sm); } return 0; } static int menu_constructor(lua_State *L) { QWidget *parent = check_winid(L, 1); Menu **m = (Menu **) lua_newuserdata(L, sizeof(PMenu *)); *m = 0; luaL_getmetatable(L, "Ipe.menu"); lua_setmetatable(L, -2); *m = new PMenu(parent); return 1; } // -------------------------------------------------------------------- class EditorThread : public QThread { public: EditorThread(const QString &cmd); protected: virtual void run(); private: QString iCommand; }; EditorThread::EditorThread(const QString &cmd) : QThread() { iCommand = cmd; } void EditorThread::run() { int result = std::system(iCommand.toUtf8()); (void) result; } class EditorDialog : public QDialog { public: EditorDialog(QWidget *parent = 0); protected: void closeEvent(QCloseEvent *ev); }; EditorDialog::EditorDialog(QWidget *parent) : QDialog(parent) { QGridLayout *lo = new QGridLayout; setLayout(lo); setWindowTitle("Ipe: waiting"); QLabel *l = new QLabel("Waiting for external editor", this); lo->addWidget(l, 0, 0); } void EditorDialog::closeEvent(QCloseEvent *ev) { ev->ignore(); } static int ipeui_wait(lua_State *L) { QString cmd = checkstring(L, 1); EditorDialog *dialog = new EditorDialog(); EditorThread *thread = new EditorThread(cmd); dialog->connect(thread, SIGNAL(finished()), SLOT(accept())); thread->start(); dialog->exec(); delete dialog; delete thread; return 0; } // -------------------------------------------------------------------- PTimer::PTimer(lua_State *L0, int lua_object, const char *method) : Timer(L0, lua_object, method) { iTimer = new QTimer(); connect(iTimer, SIGNAL(timeout()), SLOT(elapsed())); } PTimer::~PTimer() { delete iTimer; } void PTimer::elapsed() { if (iSingleShot) iTimer->stop(); callLua(); } int PTimer::setInterval(lua_State *L) { int t = luaL_checkint(L, 2); iTimer->setInterval(t); return 0; } int PTimer::active(lua_State *L) { lua_pushboolean(L, iTimer->isActive()); return 1; } int PTimer::start(lua_State *L) { iTimer->start(); return 0; } int PTimer::stop(lua_State *L) { iTimer->stop(); return 0; } // -------------------------------------------------------------------- static int timer_constructor(lua_State *L) { luaL_argcheck(L, lua_istable(L, 1), 1, "argument is not a table"); const char *method = luaL_checkstring(L, 2); Timer **t = (Timer **) lua_newuserdata(L, sizeof(Timer *)); *t = 0; luaL_getmetatable(L, "Ipe.timer"); lua_setmetatable(L, -2); // create a table with weak reference to Lua object lua_createtable(L, 1, 1); lua_pushliteral(L, "v"); lua_setfield(L, -2, "__mode"); lua_pushvalue(L, -1); lua_setmetatable(L, -2); lua_pushvalue(L, 1); lua_rawseti(L, -2, 1); int lua_object = luaL_ref(L, LUA_REGISTRYINDEX); *t = new PTimer(L, lua_object, method); return 1; } // -------------------------------------------------------------------- static int ipeui_getColor(lua_State *L) { QWidget *parent = check_winid(L, 1); QString title = checkstring(L, 2); QColor initial = QColor::fromRgbF(luaL_checknumber(L, 3), luaL_checknumber(L, 4), luaL_checknumber(L, 5)); #if QT_VERSION >= 0x040500 QColor changed = QColorDialog::getColor(initial, parent, title); #else QColor changed = QColorDialog::getColor(initial, parent); #endif if (changed.isValid()) { lua_pushnumber(L, changed.redF()); lua_pushnumber(L, changed.greenF()); lua_pushnumber(L, changed.blueF()); return 3; } else return 0; } // -------------------------------------------------------------------- static int ipeui_fileDialog(lua_State *L) { static const char * const typenames[] = { "open", "save", 0 }; QWidget *parent = check_winid(L, 1); int type = luaL_checkoption(L, 2, 0, typenames); QString caption = checkstring(L, 3); QString filter = checkstring(L, 4); QString dir; if (!lua_isnoneornil(L, 5)) dir = checkstring(L, 5); QString selected; if (!lua_isnoneornil(L, 6)) selected = checkstring(L, 6); QFileDialog dialog(parent); dialog.setWindowTitle(caption); dialog.setNameFilter(filter); dialog.setConfirmOverwrite(false); if (type == 0) { dialog.setFileMode(QFileDialog::ExistingFile); dialog.setAcceptMode(QFileDialog::AcceptOpen); } else { dialog.setFileMode(QFileDialog::AnyFile); dialog.setAcceptMode(QFileDialog::AcceptSave); } if (!selected.isNull()) dialog.selectFilter(selected); if (!dir.isNull()) dialog.setDirectory(dir); if (dialog.exec() == QDialog::Accepted) { QStringList fns = dialog.selectedFiles(); if (!fns.isEmpty()) { push_string(L, fns[0]); push_string(L, dialog.selectedNameFilter()); return 2; } } return 0; } // -------------------------------------------------------------------- static int ipeui_messageBox(lua_State *L) { static const char * const options[] = { "none", "warning", "information", "question", "critical", 0 }; static const char * const buttontype[] = { "ok", "okcancel", "yesnocancel", "discardcancel", "savediscardcancel", 0 }; QWidget *parent = check_winid(L, 1); int type = luaL_checkoption(L, 2, "none", options); QString text = checkstring(L, 3); const char *details = 0; if (!lua_isnoneornil(L, 4)) details = luaL_checkstring(L, 4); int buttons = 0; if (lua_isnumber(L, 5)) buttons = luaL_checkint(L, 5); else if (!lua_isnoneornil(L, 5)) buttons = luaL_checkoption(L, 5, 0, buttontype); QMessageBox msgBox(parent); msgBox.setText(text); if (details) msgBox.setInformativeText(QString::fromUtf8(details)); switch (type) { case 0: default: msgBox.setIcon(QMessageBox::NoIcon); break; case 1: msgBox.setIcon(QMessageBox::Warning); break; case 2: msgBox.setIcon(QMessageBox::Information); break; case 3: msgBox.setIcon(QMessageBox::Question); break; case 4: msgBox.setIcon(QMessageBox::Critical); break; } switch (buttons) { case 0: default: msgBox.setStandardButtons(QMessageBox::Ok); break; case 1: msgBox.setStandardButtons(QMessageBox::Ok|QMessageBox::Cancel); break; case 2: msgBox.setStandardButtons(QMessageBox::Yes|QMessageBox::No| QMessageBox::Cancel); break; case 3: msgBox.setStandardButtons(QMessageBox::Discard|QMessageBox::Cancel); break; case 4: msgBox.setStandardButtons(QMessageBox::Save|QMessageBox::Discard| QMessageBox::Cancel); break; } int ret = msgBox.exec(); switch (ret) { case QMessageBox::Ok: case QMessageBox::Yes: case QMessageBox::Save: lua_pushnumber(L, 1); break; case QMessageBox::No: case QMessageBox::Discard: lua_pushnumber(L, 0); break; case QMessageBox::Cancel: default: lua_pushnumber(L, -1); break; } return 1; } // -------------------------------------------------------------------- static int ipeui_closeAllWindows(lua_State *L) { QApplication::closeAllWindows(); return 0; } static int ipeui_setClipboard(lua_State *L) { QString data = checkstring(L, 1); QClipboard *cb = QApplication::clipboard(); cb->setText(data); return 0; } static int ipeui_clipboard(lua_State *L) { QClipboard *cb = QApplication::clipboard(); QString data = cb->text(); push_string(L, data); return 1; } static int ipeui_local8bit(lua_State *L) { QString data = checkstring(L, 1); QByteArray l8 = data.toLocal8Bit(); lua_pushstring(L, l8.data()); return 1; } static int ipeui_currentDateTime(lua_State *L) { QDateTime dt = QDateTime::currentDateTime(); QString mod; mod.sprintf("%04d%02d%02d%02d%02d%02d", dt.date().year(), dt.date().month(), dt.date().day(), dt.time().hour(), dt.time().minute(), dt.time().second()); push_string(L, mod); return 1; } #if defined(WIN32) static int ipeui_startBrowser(lua_State *L) { const char *url = luaL_checkstring(L, 1); ShellExecuteA(0, "open", url, 0, 0, 0); return 0; } #endif // -------------------------------------------------------------------- static const struct luaL_Reg ipeui_functions[] = { { "Dialog", dialog_constructor }, { "Menu", menu_constructor }, { "Timer", timer_constructor }, { "getColor", ipeui_getColor }, { "fileDialog", ipeui_fileDialog }, { "messageBox", ipeui_messageBox }, { "WaitDialog", ipeui_wait }, { "closeAllWindows", ipeui_closeAllWindows }, { "currentDateTime", ipeui_currentDateTime }, { "setClipboard", ipeui_setClipboard }, { "clipboard", ipeui_clipboard }, { "local8bit", ipeui_local8bit }, #ifdef WIN32 { "startBrowser", ipeui_startBrowser }, #endif { 0, 0}, }; // -------------------------------------------------------------------- int luaopen_ipeui(lua_State *L) { luaL_newlib(L, ipeui_functions); lua_setglobal(L, "ipeui"); luaopen_ipeui_common(L); return 0; } // -------------------------------------------------------------------- ipe-7.1.4/src/ipeui/Makefile0000644000175000017500000000212312120621776015516 0ustar otfriedotfried# -------------------------------------------------------------------- # Makefile for ipeui # -------------------------------------------------------------------- OBJDIR = $(BUILDDIR)/obj/ipeui include ../common.mak TARGET = $(call dll_target,ipeui) MAKE_SYMLINKS = $(call dll_symlinks,ipeui) SONAME = $(call soname,ipeui) INSTALL_SYMLINKS = $(call install_symlinks,ipeui) CPPFLAGS += $(UI_CFLAGS) $(LUA_CFLAGS) LIBS += $(UI_LIBS) $(LUA_LIBS) CXXFLAGS += $(DLL_CFLAGS) all: $(TARGET) sources = ipeui_common.cpp qt_sources = ipeui_qt.cpp moc_headers = ipeui_qt.h win_sources = ipeui_win.cpp gtk_sources = ipeui_gtk.cpp $(TARGET): $(objects) $(MAKE_LIBDIR) $(CXX) $(LDFLAGS) $(DLL_LDFLAGS) $(SONAME) -o $@ $^ $(LIBS) $(MAKE_SYMLINKS) clean: @-rm -f $(objects) $(TARGET) $(DEPEND) $(DEPEND): Makefile $(MAKE_DEPEND) -include $(DEPEND) install: $(TARGET) $(INSTALL_DIR) $(INSTALL_ROOT)$(IPELIBDIR) $(INSTALL_PROGRAMS) $(TARGET) $(INSTALL_ROOT)$(IPELIBDIR) $(INSTALL_SYMLINKS) # -------------------------------------------------------------------- ipe-7.1.4/src/ipeui/ipeui_qt.h0000644000175000017500000000630012120621776016047 0ustar otfriedotfried// -*- C++ -*- // -------------------------------------------------------------------- // A UI toolkit for Lua, QT version // -------------------------------------------------------------------- /* This file is part of the extensible drawing editor Ipe. Copyright (C) 1993-2013 Otfried Cheong Ipe is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. As a special exception, you have permission to link Ipe with the CGAL library and distribute executables, as long as you follow the requirements of the Gnu General Public License in regard to all of the software in the executable aside from CGAL. Ipe 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 General Public License for more details. You should have received a copy of the GNU General Public License along with Ipe; if not, you can find it at "http://www.gnu.org/copyleft/gpl.html", or write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ #ifndef IPEUI_QT__H #define IPEUI_QT_H #include "ipeui_common.h" #include #include #include #include class QTimer; class QTextEdit; // -------------------------------------------------------------------- class MenuAction : public QAction { Q_OBJECT public: MenuAction(const QString &name, int number, const QString &item, const QString &text, QWidget *parent); QString name() const { return iName; } QString itemName() const { return iItemName; } int number() const { return iNumber; } private: QString iName; QString iItemName; int iNumber; }; class PMenu : public Menu { public: PMenu(WINID parent); virtual ~PMenu(); virtual int add(lua_State *L); virtual int execute(lua_State *L); private: QMenu *iMenu; }; // -------------------------------------------------------------------- class PTimer : public QObject, public Timer { Q_OBJECT public: PTimer(lua_State *L0, int lua_object, const char *method); virtual ~PTimer(); virtual int setInterval(lua_State *L); virtual int active(lua_State *L); virtual int start(lua_State *L); virtual int stop(lua_State *L); private slots: void elapsed(); private: QTimer *iTimer; }; // -------------------------------------------------------------------- class PDialog : public QDialog, public Dialog { Q_OBJECT public: PDialog(lua_State *L0, WINID parent, const char *caption); ~PDialog(); QGridLayout *gridlayout() { return iGrid; } private slots: void notifyLua(); protected: virtual void setMapped(lua_State *L, int idx); virtual bool buildAndRun(int w, int h); virtual void retrieveValues(); virtual void enableItem(int idx, bool value); protected: virtual void keyPressEvent(QKeyEvent *e); private: std::vector iWidgets; QGridLayout *iGrid; QHBoxLayout *iButtonArea; }; // -------------------------------------------------------------------- #endif ipe-7.1.4/src/ipeui/ipeui_common.cpp0000644000175000017500000004211512120621776017252 0ustar otfriedotfried// -------------------------------------------------------------------- // Lua bindings for UI, platform-neutral common part // -------------------------------------------------------------------- /* This file is part of the extensible drawing editor Ipe. Copyright (C) 1993-2013 Otfried Cheong Ipe is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. As a special exception, you have permission to link Ipe with the CGAL library and distribute executables, as long as you follow the requirements of the Gnu General Public License in regard to all of the software in the executable aside from CGAL. Ipe 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 General Public License for more details. You should have received a copy of the GNU General Public License along with Ipe; if not, you can find it at "http://www.gnu.org/copyleft/gpl.html", or write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ #include "ipeui_common.h" // -------------------------------------------------------------------- WINID check_winid(lua_State *L, int i) { if (lua_isnil(L, i)) return 0; WINID *w = (WINID *) luaL_checkudata(L, i, "Ipe.winid"); return *w; } void push_winid(lua_State *L, WINID win) { WINID *w = (WINID *) lua_newuserdata(L, sizeof(WINID)); *w = win; luaL_getmetatable(L, "Ipe.winid"); lua_setmetatable(L, -2); } static int winid_tostring(lua_State *L) { check_winid(L, 1); lua_pushfstring(L, "GtkWidget@%p", lua_topointer(L, 1)); return 1; } static const struct luaL_Reg winid_methods[] = { { "__tostring", winid_tostring }, { 0, 0 } }; // -------------------------------------------------------------------- String::String() { iImp = 0; } String::String(const String &rhs) { iImp = rhs.iImp; if (iImp) iImp->iRefCount += 1; } String::String(const char *str) { if (str) { iImp = new Imp; iImp->iRefCount = 1; iImp->iData = strdup(str); } else iImp = 0; } String &String::operator=(const String &rhs) { if (this != &rhs) { if (iImp) { iImp->iRefCount -= 1; if (iImp->iRefCount == 0) { free(iImp->iData); delete iImp; } } iImp = rhs.iImp; if (iImp) iImp->iRefCount += 1; } return *this; } String::~String() { if (iImp) { iImp->iRefCount -= 1; if (iImp->iRefCount == 0) { free(iImp->iData); delete iImp; } } } // -------------------------------------------------------------------- Dialog::Dialog(lua_State *L0, WINID parent, const char *caption) : iCaption(caption) { L = L0; iParent = parent; iLuaDialog = LUA_NOREF; hDialog = NULL; iIgnoreEscape = false; iNoRows = 1; iNoCols = 1; // TODO: handle "Ctrl+Return" } Dialog::~Dialog() { // dereference lua methods for (int i = 0; i < int(iElements.size()); ++i) luaL_unref(L, LUA_REGISTRYINDEX, iElements[i].lua_method); luaL_unref(L, LUA_REGISTRYINDEX, iLuaDialog); } void Dialog::callLua(int luaMethod) { // only call back to Lua during execute() if (iLuaDialog == LUA_NOREF) return; lua_rawgeti(L, LUA_REGISTRYINDEX, luaMethod); lua_rawgeti(L, LUA_REGISTRYINDEX, iLuaDialog); lua_call(L, 1, 0); } // name, label, action int Dialog::addButton(lua_State *L) { SElement m; m.name = String(luaL_checkstring(L, 2)); m.type = EButton; m.lua_method = LUA_NOREF; m.flags = 0; m.row = -1; m.col = -1; m.rowspan = 1; m.colspan = 1; m.text = String(luaL_checkstring(L, 3)); if (lua_isstring(L, 4)) { const char *s = lua_tostring(L, 4); if (!strcmp(s, "accept")) m.flags |= EAccept; else if (!strcmp(s, "reject")) m.flags |= EReject; else luaL_argerror(L, 4, "unknown action"); } else { luaL_argcheck(L, lua_isfunction(L, 4), 4, "unknown action"); lua_pushvalue(L, 4); m.lua_method = luaL_ref(L, LUA_REGISTRYINDEX); } m.minHeight = 16; m.minWidth = 4 * m.text.len() + 8; if (m.minWidth < 64) m.minWidth = 64; iElements.push_back(m); return 0; } int Dialog::add(lua_State *L) { static const char * const typenames[] = { "button", "text", "list", "label", "combo", "checkbox", "input", 0 }; SElement m; m.name = String(luaL_checkstring(L, 2)); m.type = TType(luaL_checkoption(L, 3, 0, typenames)); luaL_checktype(L, 4, LUA_TTABLE); m.lua_method = LUA_NOREF; m.flags = 0; m.row = luaL_checkint(L, 5) - 1; m.col = luaL_checkint(L, 6) - 1; m.rowspan = 1; m.colspan = 1; if (!lua_isnoneornil(L, 7)) m.rowspan = luaL_checkint(L, 7); if (!lua_isnoneornil(L, 8)) m.colspan = luaL_checkint(L, 8); if (m.row + m.rowspan > iNoRows) iNoRows = m.row + m.rowspan; if (m.col + m.colspan > iNoCols) iNoCols = m.col + m.colspan; switch (m.type) { case EButton: addButtonItem(L, m); break; case ETextEdit: addTextEdit(L, m); break; case EList: addList(L, m); break; case ELabel: addLabel(L, m); break; case ECombo: addCombo(L, m); break; case ECheckBox: addCheckbox(L, m); break; case EInput: addInput(L, m); break; default: break; } iElements.push_back(m); return 0; } void Dialog::addLabel(lua_State *L, SElement &m) { lua_getfield(L, 4, "label"); luaL_argcheck(L, lua_isstring(L, -1), 4, "no label"); m.text = String(lua_tostring(L, -1)); lua_pop(L, 1); // label m.minHeight = 16; m.minWidth = 4 * m.text.len(); } void Dialog::addButtonItem(lua_State *L, SElement &m) { lua_getfield(L, 4, "label"); luaL_argcheck(L, lua_isstring(L, -1), 4, "no button label"); const char *label = lua_tostring(L, -1); m.text = String(label); lua_getfield(L, 4, "action"); if (lua_isstring(L, -1)) { const char *s = lua_tostring(L, -1); if (!strcmp(s, "accept")) m.flags |= EAccept; else if (!strcmp(s, "reject")) m.flags |= EReject; else luaL_argerror(L, 4, "unknown action"); } else if (lua_isfunction(L, -1)) { lua_pushvalue(L, -1); m.lua_method = luaL_ref(L, LUA_REGISTRYINDEX); } else if (!lua_isnil(L, -1)) luaL_argerror(L, 4, "unknown action type"); lua_pop(L, 2); // action, label m.minHeight = 16; m.minWidth = 4 * m.text.len() + 8; if (m.minWidth < 64) m.minWidth = 64; } void Dialog::addCheckbox(lua_State *L, SElement &m) { lua_getfield(L, 4, "label"); luaL_argcheck(L, lua_isstring(L, -1), 4, "no label"); m.text = String(lua_tostring(L, -1)); lua_getfield(L, 4, "action"); if (!lua_isnil(L, -1)) { luaL_argcheck(L, lua_isfunction(L, -1), 4, "unknown action type"); lua_pushvalue(L, -1); m.lua_method = luaL_ref(L, LUA_REGISTRYINDEX); } lua_pop(L, 2); // action, label m.value = 0; m.minHeight = 16; m.minWidth = 4 * m.text.len() + 32; } void Dialog::addInput(lua_State *L, SElement &m) { m.minHeight = 12; m.minWidth = 100; } void Dialog::addTextEdit(lua_State *L, SElement &m) { lua_getfield(L, 4, "read_only"); if (lua_toboolean(L, -1)) m.flags |= EReadOnly; lua_getfield(L, 4, "syntax"); if (!lua_isnil(L, -1)) { const char *s = lua_tostring(L, -1); if (!strcmp(s, "logfile")) { m.flags |= ELogFile; } else if (!strcmp(s, "xml")) { m.flags |= EXml; } else if (!strcmp(s, "latex")) { } else luaL_argerror(L, 4, "unknown syntax"); } lua_pop(L, 2); // syntax, read_only m.minHeight = 48; m.minWidth = 100; } void Dialog::setListItems(lua_State *L, int index, SElement &m) { int no = lua_rawlen(L, index); m.minWidth = 48; for (int i = 1; i <= no; ++i) { lua_rawgeti(L, index, i); luaL_argcheck(L, lua_isstring(L, -1), index, "items must be strings"); const char *item = lua_tostring(L, -1); m.items.push_back(String(item)); int w = 4 * strlen(item) + 16; if (w > m.minWidth) m.minWidth = w; lua_pop(L, 1); // item } } void Dialog::addList(lua_State *L, SElement &m) { setListItems(L, 4, m); m.value = 0; m.minHeight = 48; } void Dialog::addCombo(lua_State *L, SElement &m) { setListItems(L, 4, m); m.value = 0; m.minHeight = 16; } int Dialog::findElement(lua_State *L, int index) { const char *name = luaL_checkstring(L, index); for (int i = 0; i < int(iElements.size()); ++i) { if (!strcmp(iElements[i].name.z(), name)) return i; } return luaL_argerror(L, index, "no such element in dialog"); } int Dialog::set(lua_State *L) { const char *s = luaL_checkstring(L, 2); if (!strcmp(s, "ignore-cancel")) { iIgnoreEscape = lua_toboolean(L, 3); return 0; } int idx = findElement(L, 2); // set internal representation setUnmapped(L, idx); // if dialog is on screen, also set there if (iLuaDialog != LUA_NOREF) setMapped(L, idx); return 0; } void Dialog::setUnmapped(lua_State *L, int idx) { SElement &m = iElements[idx]; switch (m.type) { case ELabel: case ETextEdit: case EInput: m.text = String(luaL_checkstring(L, 3)); break; case EList: case ECombo: if (lua_isnumber(L, 3)) { int n = luaL_checkint(L, 3); luaL_argcheck(L, 1 <= n && n <= int(m.items.size()), 3, "list index out of bounds"); m.value = n - 1; } else { luaL_checktype(L, 3, LUA_TTABLE); m.items.clear(); setListItems(L, 3, m); m.value = 0; } break; case ECheckBox: m.value = lua_toboolean(L, 3); break; default: luaL_argerror(L, 2, "no suitable element"); } } int Dialog::get(lua_State *L) { if (iLuaDialog != LUA_NOREF) retrieveValues(); int idx = findElement(L, 2); SElement &m = iElements[idx]; switch (m.type) { case ETextEdit: case EInput: lua_pushstring(L, m.text.z()); return 1; case EList: case ECombo: lua_pushinteger(L, m.value + 1); return 1; case ECheckBox: lua_pushboolean(L, m.value); return 1; default: return luaL_argerror(L, 2, "no suitable element"); } } bool Dialog::execute(lua_State *L, int w, int h) { // remember Lua object for dialog for callbacks lua_pushvalue(L, 1); iLuaDialog = luaL_ref(L, LUA_REGISTRYINDEX); bool result = buildAndRun(w, h); // execute dialog // discard reference to dialog object // (otherwise the circular reference will stop Lua gc) luaL_unref(L, LUA_REGISTRYINDEX, iLuaDialog); iLuaDialog = LUA_NOREF; return result; } int Dialog::setEnabled(lua_State *L) { int idx = findElement(L, 2); bool value = lua_toboolean(L, 3); if (iLuaDialog != LUA_NOREF) // mapped enableItem(idx, value); else if (value) iElements[idx].flags &= ~EDisabled; else iElements[idx].flags |= EDisabled; return 0; } int Dialog::setStretch(lua_State *L) { static const char * const typenames[] = { "row", "column", 0 }; while (int(iColStretch.size()) < iNoCols) iColStretch.push_back(0); while (int(iRowStretch.size()) < iNoRows) iRowStretch.push_back(0); int type = luaL_checkoption(L, 2, 0, typenames); int rowcol = luaL_checkint(L, 3) - 1; int stretch = luaL_checkint(L, 4); if (type == 0) { luaL_argcheck(L, 0 <= rowcol && rowcol < iNoRows, 3, "Row index out of range"); iRowStretch[rowcol] = stretch; } else { luaL_argcheck(L, 0 <= rowcol && rowcol < iNoCols, 3, "Column index out of range"); iColStretch[rowcol] = stretch; } return 0; } // -------------------------------------------------------------------- static int dialog_tostring(lua_State *L) { check_dialog(L, 1); lua_pushfstring(L, "Dialog@%p", lua_topointer(L, 1)); return 1; } static int dialog_destructor(lua_State *L) { //fprintf(stderr, "Dialog::~Dialog()\n"); Dialog **dlg = check_dialog(L, 1); delete (*dlg); *dlg = 0; return 0; } static int dialog_execute(lua_State *L) { Dialog **dlg = check_dialog(L, 1); int w = 0; int h = 0; if (!lua_isnoneornil(L, 2)) { luaL_argcheck(L, lua_istable(L, 2), 2, "argument is not a table"); lua_rawgeti(L, 2, 1); luaL_argcheck(L, lua_isnumber(L, -1), 2, "width is not a number"); lua_rawgeti(L, 2, 2); luaL_argcheck(L, lua_isnumber(L, -1), 2, "height is not a number"); w = lua_tointeger(L, -2); h = lua_tointeger(L, -1); lua_pop(L, 2); // w & h } lua_pushboolean(L, (*dlg)->execute(L, w, h)); return 1; } static int dialog_setStretch(lua_State *L) { Dialog **dlg = check_dialog(L, 1); return (*dlg)->setStretch(L); } static int dialog_add(lua_State *L) { Dialog **dlg = check_dialog(L, 1); return (*dlg)->add(L); } static int dialog_addButton(lua_State *L) { Dialog **dlg = check_dialog(L, 1); return (*dlg)->addButton(L); } static int dialog_set(lua_State *L) { Dialog **dlg = check_dialog(L, 1); return (*dlg)->set(L); } static int dialog_get(lua_State *L) { Dialog **dlg = check_dialog(L, 1); return (*dlg)->get(L); } static int dialog_setEnabled(lua_State *L) { Dialog **dlg = check_dialog(L, 1); return (*dlg)->setEnabled(L); } // -------------------------------------------------------------------- static const struct luaL_Reg dialog_methods[] = { { "__tostring", dialog_tostring }, { "__gc", dialog_destructor }, { "execute", dialog_execute }, { "setStretch", dialog_setStretch }, { "add", dialog_add }, { "addButton", dialog_addButton }, { "set", dialog_set }, { "get", dialog_get }, { "setEnabled", dialog_setEnabled }, { 0, 0 } }; // -------------------------------------------------------------------- Menu::~Menu() { // empty } // -------------------------------------------------------------------- static int menu_tostring(lua_State *L) { check_menu(L, 1); lua_pushfstring(L, "Menu@%p", lua_topointer(L, 1)); return 1; } static int menu_destructor(lua_State *L) { //fprintf(stderr, "Menu::~Menu()\n"); Menu **m = check_menu(L, 1); delete *m; *m = 0; return 0; } static int menu_execute(lua_State *L) { Menu **m = check_menu(L, 1); return (*m)->execute(L); } static int menu_add(lua_State *L) { Menu **m = check_menu(L, 1); return (*m)->add(L); } // -------------------------------------------------------------------- static const struct luaL_Reg menu_methods[] = { { "__tostring", menu_tostring }, { "__gc", menu_destructor }, { "execute", menu_execute }, { "add", menu_add }, { 0, 0 } }; // -------------------------------------------------------------------- Timer::Timer(lua_State *L0, int lua_object, const char *method) : iMethod(method) { L = L0; iLuaObject = lua_object; iSingleShot = false; } Timer::~Timer() { luaL_unref(L, LUA_REGISTRYINDEX, iLuaObject); } void Timer::callLua() { lua_rawgeti(L, LUA_REGISTRYINDEX, iLuaObject); lua_rawgeti(L, -1, 1); // get Lua object if (lua_isnil(L, -1)) { lua_pop(L, 2); // pop weak table, nil return; } lua_getfield(L, -1, iMethod.z()); if (lua_isnil(L, -1)) { lua_pop(L, 3); // pop weak table, table, nil return; } lua_remove(L, -3); // remove weak table lua_insert(L, -2); // stack is now: method, table lua_call(L, 1, 0); // call method } int Timer::setSingleShot(lua_State *L) { bool t = lua_toboolean(L, 2); iSingleShot = t; return 0; } // -------------------------------------------------------------------- static int timer_tostring(lua_State *L) { check_timer(L, 1); lua_pushfstring(L, "Timer@%p", lua_topointer(L, 1)); return 1; } static int timer_destructor(lua_State *L) { Timer **t = check_timer(L, 1); //fprintf(stderr, "Timer::~Timer()\n"); delete *t; *t = 0; return 0; } // -------------------------------------------------------------------- static int timer_start(lua_State *L) { Timer **t = check_timer(L, 1); return (*t)->start(L); } static int timer_stop(lua_State *L) { Timer **t = check_timer(L, 1); return (*t)->stop(L); } static int timer_active(lua_State *L) { Timer **t = check_timer(L, 1); return (*t)->active(L); } static int timer_setinterval(lua_State *L) { Timer **t = check_timer(L, 1); return (*t)->setInterval(L); } static int timer_setsingleshot(lua_State *L) { Timer **t = check_timer(L, 1); return (*t)->setSingleShot(L); } // -------------------------------------------------------------------- static const struct luaL_Reg timer_methods[] = { { "__tostring", timer_tostring }, { "__gc", timer_destructor }, { "start", timer_start }, { "stop", timer_stop }, { "active", timer_active }, { "setInterval", timer_setinterval }, { "setSingleShot", timer_setsingleshot }, { 0, 0 } }; // -------------------------------------------------------------------- static void make_metatable(lua_State *L, const char *name, const struct luaL_Reg *methods) { luaL_newmetatable(L, name); lua_pushstring(L, "__index"); lua_pushvalue(L, -2); /* pushes the metatable */ lua_settable(L, -3); /* metatable.__index = metatable */ luaL_setfuncs(L, methods, 0); lua_pop(L, 1); } int luaopen_ipeui_common(lua_State *L) { make_metatable(L, "Ipe.winid", winid_methods); make_metatable(L, "Ipe.dialog", dialog_methods); make_metatable(L, "Ipe.menu", menu_methods); make_metatable(L, "Ipe.timer", timer_methods); return 0; } // -------------------------------------------------------------------- ipe-7.1.4/src/ipeui/ipeui_gtk.cpp0000644000175000017500000006544312120621776016560 0ustar otfriedotfried// -------------------------------------------------------------------- // Lua bindings for GTK dialogs // -------------------------------------------------------------------- /* This file is part of the extensible drawing editor Ipe. Copyright (C) 1993-2013 Otfried Cheong Ipe is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. As a special exception, you have permission to link Ipe with the CGAL library and distribute executables, as long as you follow the requirements of the Gnu General Public License in regard to all of the software in the executable aside from CGAL. Ipe 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 General Public License for more details. You should have received a copy of the GNU General Public License along with Ipe; if not, you can find it at "http://www.gnu.org/copyleft/gpl.html", or write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ #include "ipeui_common.h" // -------------------------------------------------------------------- class PDialog : public Dialog { public: PDialog(lua_State *L0, WINID parent, const char *caption); virtual ~PDialog(); virtual void setMapped(lua_State *L, int idx); virtual bool buildAndRun(int w, int h); virtual void retrieveValues(); virtual void enableItem(int idx, bool value); private: static void setListBoxRow(GtkTreeView *w, int row); static GtkWidget *createListBox(const SElement &m); static void fillListStore(GtkListStore *store, const SElement &m); static void itemResponse(GtkWidget *item, PDialog *dlg); private: std::vector iWidgets; }; PDialog::PDialog(lua_State *L0, WINID parent, const char *caption) : Dialog(L0, parent, caption) { // } PDialog::~PDialog() { // } void PDialog::itemResponse(GtkWidget *item, PDialog *dlg) { for (int i = 0; i < int(dlg->iWidgets.size()); ++i) { if (dlg->iWidgets[i] == item) { dlg->callLua(dlg->iElements[i].lua_method); return; } } } void PDialog::setMapped(lua_State *L, int idx) { SElement &m = iElements[idx]; GtkWidget *w = iWidgets[idx]; switch (m.type) { case ELabel: gtk_label_set_text(GTK_LABEL(w), m.text.z()); break; case ECheckBox: gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(w), m.value); break; case ETextEdit: gtk_text_buffer_set_text(gtk_text_view_get_buffer(GTK_TEXT_VIEW(w)), m.text.z(), -1); break; case EInput: gtk_entry_set_text(GTK_ENTRY(w), m.text.z()); break; case EList: if (lua_istable(L, 3)) { GtkTreeModel *mod = gtk_tree_view_get_model(GTK_TREE_VIEW(w)); fillListStore(GTK_LIST_STORE(mod), m); } setListBoxRow(GTK_TREE_VIEW(w), m.value); break; case ECombo: if (lua_istable(L, 3)) { GtkTreeModel *mod = gtk_combo_box_get_model(GTK_COMBO_BOX(w)); fillListStore(GTK_LIST_STORE(mod), m); } gtk_combo_box_set_active(GTK_COMBO_BOX(w), m.value); break; default: break; // EButton } } static String getTextEdit(GtkWidget *w) { GtkTextBuffer *buffer = gtk_text_view_get_buffer(GTK_TEXT_VIEW(w)); GtkTextIter start; GtkTextIter end; gtk_text_buffer_get_iter_at_offset(buffer, &start, 0); gtk_text_buffer_get_iter_at_offset(buffer, &end, -1); gchar *s = gtk_text_buffer_get_text(buffer, &start, &end, TRUE); return String(s); } void PDialog::retrieveValues() { for (int i = 0; i < int(iElements.size()); ++i) { SElement &m = iElements[i]; GtkWidget *w = iWidgets[i]; switch (m.type) { case EInput: m.text = String(gtk_entry_get_text(GTK_ENTRY(w))); break; case ETextEdit: m.text = getTextEdit(w); break; case EList: { GtkTreeSelection *s = gtk_tree_view_get_selection(GTK_TREE_VIEW(w)); GtkTreeModel *model; GtkTreeIter iter; if (gtk_tree_selection_get_selected(s, &model, &iter)) { gint *path = gtk_tree_path_get_indices(gtk_tree_model_get_path(model, &iter)); m.value = path[0]; } else m.value = 0; } break; case ECombo: m.value = gtk_combo_box_get_active(GTK_COMBO_BOX(w)); break; case ECheckBox: m.value = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(w)); break; default: break; // label and button - nothing to do } } } void PDialog::enableItem(int idx, bool value) { gtk_widget_set_sensitive(iWidgets[idx], value); } void PDialog::setListBoxRow(GtkTreeView *w, int row) { GtkTreeSelection *s = gtk_tree_view_get_selection(w); GtkTreePath *path = gtk_tree_path_new_from_indices(row, -1); gtk_tree_selection_select_path(s, path); gtk_tree_path_free(path); } void PDialog::fillListStore(GtkListStore *store, const SElement &m) { GtkTreeIter iter; gtk_list_store_clear(store); for (int k = 0; k < int(m.items.size()); ++k) { gtk_list_store_append(store, &iter); gtk_list_store_set(store, &iter, 0, m.items[k].z(), -1); } } GtkWidget *PDialog::createListBox(const SElement &m) { GtkListStore *store = gtk_list_store_new(1, G_TYPE_STRING); fillListStore(store, m); GtkWidget *w = gtk_tree_view_new_with_model(GTK_TREE_MODEL(store)); g_object_unref(G_OBJECT(store)); GtkCellRenderer *renderer = gtk_cell_renderer_text_new (); // g_object_set(G_OBJECT(renderer), "foreground", "red", NULL); GtkTreeViewColumn *column = gtk_tree_view_column_new_with_attributes("Title", renderer, "text", 0, NULL); gtk_tree_view_append_column(GTK_TREE_VIEW(w), column); gtk_tree_view_set_headers_visible(GTK_TREE_VIEW(w), false); GtkTreeSelection *s = gtk_tree_view_get_selection(GTK_TREE_VIEW(w)); gtk_tree_selection_set_mode(s, GTK_SELECTION_SINGLE); setListBoxRow(GTK_TREE_VIEW(w), m.value); return w; } static GtkWidget *addScrollBar(GtkWidget *w) { GtkWidget *ww = gtk_scrolled_window_new(NULL, NULL); gtk_scrolled_window_set_shadow_type(GTK_SCROLLED_WINDOW(ww), GTK_SHADOW_ETCHED_IN); gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(ww), GTK_POLICY_NEVER, GTK_POLICY_AUTOMATIC); gtk_container_add(GTK_CONTAINER(ww), w); return ww; } static void ctrlEnterResponse(GtkWidget *, GtkDialog *dlg) { gtk_dialog_response(dlg, GTK_RESPONSE_ACCEPT); } static void escapeResponse(GtkWidget *, GtkDialog *dlg) { // catching escape, doing nothing } bool PDialog::buildAndRun(int w, int h) { hDialog = gtk_dialog_new(); gtk_window_set_title(GTK_WINDOW(hDialog), iCaption.z()); GtkAccelGroup *accel_group = gtk_accel_group_new(); gtk_window_add_accel_group(GTK_WINDOW(hDialog), accel_group); guint accel_key; GdkModifierType accel_mods; gtk_accelerator_parse("Return", &accel_key, &accel_mods); gtk_accel_group_connect(accel_group, accel_key, accel_mods, GtkAccelFlags(0), g_cclosure_new(G_CALLBACK(ctrlEnterResponse), hDialog, NULL)); if (iIgnoreEscape) { gtk_accelerator_parse("Escape", &accel_key, &accel_mods); gtk_accel_group_connect(accel_group, accel_key, accel_mods, GtkAccelFlags(0), g_cclosure_new(G_CALLBACK(escapeResponse), hDialog, NULL)); } if (w > 0 && h > 0) gtk_window_set_default_size(GTK_WINDOW(hDialog), w, h); GtkWidget *ca = gtk_dialog_get_content_area(GTK_DIALOG(hDialog)); GtkWidget *grid = gtk_table_new(iNoRows, iNoCols, FALSE); gtk_table_set_row_spacings(GTK_TABLE(grid), 8); gtk_table_set_col_spacings(GTK_TABLE(grid), 8); gtk_table_set_homogeneous(GTK_TABLE(grid), FALSE); gtk_container_set_border_width(GTK_CONTAINER(grid), 12); gtk_box_pack_start(GTK_BOX(ca), grid, TRUE, TRUE, 0); gtk_widget_show(grid); GtkWidget *aa = gtk_dialog_get_action_area(GTK_DIALOG(hDialog)); for (int i = 0; i < int(iElements.size()); ++i) { SElement &m = iElements[i]; GtkWidget *w = 0; GtkWidget *ww = 0; // for alignment int xOptions = 0; // GTK_EXPAND|GTK_SHRINK|GTK_FILL int yOptions = 0; // GTK_EXPAND|GTK_SHRINK|GTK_FILL if (m.row < 0) { if (m.flags & EAccept) { w = gtk_dialog_add_button(GTK_DIALOG(hDialog), m.text.z(), GTK_RESPONSE_ACCEPT); gtk_widget_set_can_default(w, TRUE); gtk_widget_grab_default(w); } else if (m.flags & EReject) w = gtk_dialog_add_button(GTK_DIALOG(hDialog), m.text.z(), GTK_RESPONSE_ACCEPT); else { w = gtk_button_new_with_label(m.text.z()); gtk_box_pack_start(GTK_BOX(aa), w, FALSE, FALSE, 0); gtk_widget_show(w); if (m.lua_method) g_signal_connect(w, "clicked", G_CALLBACK(itemResponse), this); } } else { switch (m.type) { case ELabel: ww = gtk_alignment_new(0.0, 0.5, 0.0, 1.0); w = gtk_label_new(m.text.z()); gtk_container_add(GTK_CONTAINER(ww), w); xOptions |= GTK_FILL; // left align in cell break; case EButton: w = gtk_button_new_with_label(m.text.z()); break; case ECheckBox: w = gtk_check_button_new_with_label(m.text.z()); if (m.lua_method) g_signal_connect(w, "toggled", G_CALLBACK(itemResponse), this); gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(w), m.value); break; case EInput: w = gtk_entry_new(); gtk_entry_set_activates_default(GTK_ENTRY(w), TRUE); xOptions |= GTK_FILL; break; case ETextEdit: w = gtk_text_view_new(); gtk_text_view_set_editable(GTK_TEXT_VIEW(w), !(m.flags & EReadOnly)); gtk_text_buffer_set_text(gtk_text_view_get_buffer(GTK_TEXT_VIEW(w)), m.text.z(), -1); gtk_text_view_set_wrap_mode(GTK_TEXT_VIEW(w), GTK_WRAP_WORD); ww = addScrollBar(w); xOptions |= GTK_FILL; yOptions |= GTK_FILL; break; case ECombo: { ww = gtk_alignment_new(0.5, 0.0, 1.0, 0.0); GtkListStore *store = gtk_list_store_new(1, G_TYPE_STRING); fillListStore(store, m); w = gtk_combo_box_new_with_model(GTK_TREE_MODEL(store)); GtkCellRenderer *renderer = gtk_cell_renderer_text_new(); gtk_cell_layout_pack_start(GTK_CELL_LAYOUT(w), renderer, TRUE); gtk_cell_layout_add_attribute(GTK_CELL_LAYOUT(w), renderer, "text", 0); gtk_container_add(GTK_CONTAINER(ww), w); gtk_combo_box_set_active(GTK_COMBO_BOX(w), m.value); xOptions |= GTK_FILL; yOptions |= GTK_FILL; // align at top } break; case EList: w = createListBox(m); ww = addScrollBar(w); xOptions |= GTK_FILL; yOptions |= GTK_FILL; break; default: break; } for (int r = m.row; r < m.row + m.rowspan; ++r) if (iRowStretch[r] > 0) yOptions |= GTK_EXPAND; for (int c = m.col; c < m.col + m.colspan; ++c) if (iColStretch[c] > 0) xOptions |= GTK_EXPAND; if (ww == 0) ww = w; if (ww != 0) { gtk_table_attach(GTK_TABLE(grid), ww, m.col, m.col+m.colspan, m.row, m.row+m.rowspan, GtkAttachOptions(xOptions), GtkAttachOptions(yOptions), 0, 0); gtk_widget_show(ww); gtk_widget_show(w); } } if (m.flags & EDisabled) gtk_widget_set_sensitive(w, false); iWidgets.push_back(w); } gint result = gtk_dialog_run(GTK_DIALOG(hDialog)); retrieveValues(); // for future reference gtk_widget_destroy(hDialog); hDialog = NULL; return (result == GTK_RESPONSE_ACCEPT); } // -------------------------------------------------------------------- static int dialog_constructor(lua_State *L) { WINID parent = check_winid(L, 1); const char *s = luaL_checkstring(L, 2); Dialog **dlg = (Dialog **) lua_newuserdata(L, sizeof(Dialog *)); *dlg = 0; luaL_getmetatable(L, "Ipe.dialog"); lua_setmetatable(L, -2); *dlg = new PDialog(L, parent, s); return 1; } // -------------------------------------------------------------------- class PMenu : public Menu { public: PMenu(WINID parent); virtual ~PMenu(); virtual int add(lua_State *L); virtual int execute(lua_State *L); private: static void itemResponse(GtkWidget *item, PMenu *menu); static void deactivateResponse(GtkMenuShell *, PMenu *); static void positionResponse(GtkMenu *, gint *x, gint *y, gboolean *push_in, PMenu *menu); private: GtkWidget *iMenu; struct Item { gchar *name; gchar *itemName; int itemIndex; GtkWidget *widget; }; std::vector items; int iSelectedItem; int iPopupX; int iPopupY; }; void PMenu::itemResponse(GtkWidget *item, PMenu *menu) { for (int i = 0; i < int(menu->items.size()); ++i) { if (menu->items[i].widget == item) { menu->iSelectedItem = i; return; } } } void PMenu::deactivateResponse(GtkMenuShell *, PMenu *) { gtk_main_quit(); // drop out of nested loop } // NOT USED: Better to just let GTK use the cursor position void PMenu::positionResponse(GtkMenu *, gint *x, gint *y, gboolean *push_in, PMenu *menu) { *x = menu->iPopupX; *y = menu->iPopupY; *push_in = TRUE; } PMenu::PMenu(WINID parent) { iMenu = gtk_menu_new(); g_object_ref_sink(iMenu); g_signal_connect(iMenu, "deactivate", G_CALLBACK(deactivateResponse), this); } PMenu::~PMenu() { for (int i = 0; i < int(items.size()); ++i) { g_free(items[i].name); g_free(items[i].itemName); } g_object_unref(iMenu); } int PMenu::execute(lua_State *L) { iPopupX = luaL_checkint(L, 2); iPopupY = luaL_checkint(L, 3); iSelectedItem = -1; gtk_menu_popup(GTK_MENU(iMenu), NULL, NULL, // GtkMenuPositionFunc(positionResponse), this, NULL, NULL, 0, // initiated by button release gtk_get_current_event_time()); // nested main loop gtk_main(); if (0 <= iSelectedItem && iSelectedItem < int(items.size())) { lua_pushstring(L, items[iSelectedItem].name); lua_pushinteger(L, items[iSelectedItem].itemIndex); if (items[iSelectedItem].itemName) lua_pushstring(L, items[iSelectedItem].itemName); else lua_pushstring(L, ""); return 3; } else return 0; } static GtkWidget *colorIcon(double red, double green, double blue) { GtkWidget *w = gtk_drawing_area_new(); gtk_widget_set_size_request(w, 13, 13); GdkColor color; color.red = int(red * 65535.0); color.green = int(green * 65535.0); color.blue = int(blue * 65535.0); gtk_widget_modify_bg(w, GTK_STATE_NORMAL, &color); g_object_ref_sink(w); return w; } int PMenu::add(lua_State *L) { const char *name = luaL_checkstring(L, 2); const char *title = luaL_checkstring(L, 3); if (lua_gettop(L) == 3) { GtkWidget *w = gtk_menu_item_new_with_label(title); gtk_menu_shell_append(GTK_MENU_SHELL(iMenu), w); g_signal_connect(w, "activate", G_CALLBACK(itemResponse), this); gtk_widget_show(w); Item item; item.name = g_strdup(name); item.itemName = 0; item.itemIndex = 0; item.widget = w; items.push_back(item); } else { luaL_argcheck(L, lua_istable(L, 4), 4, "argument is not a table"); bool hasmap = !lua_isnoneornil(L, 5) && lua_isfunction(L, 5); bool hastable = !hasmap && !lua_isnoneornil(L, 5); bool hascolor = !lua_isnoneornil(L, 6) && lua_isfunction(L, 6); bool hascheck = !hascolor && !lua_isnoneornil(L, 6); if (hastable) luaL_argcheck(L, lua_istable(L, 5), 5, "argument is not a function or table"); const char *current = 0; if (hascheck) { luaL_argcheck(L, lua_isstring(L, 6), 6, "argument is not a function or string"); current = luaL_checkstring(L, 6); } GtkWidget *sm = gtk_menu_new(); int no = lua_rawlen(L, 4); for (int i = 1; i <= no; ++i) { lua_rawgeti(L, 4, i); luaL_argcheck(L, lua_isstring(L, -1), 4, "items must be strings"); const char *item = lua_tostring(L, -1); if (hastable) { lua_rawgeti(L, 5, i); luaL_argcheck(L, lua_isstring(L, -1), 5, "labels must be strings"); } else if (hasmap) { lua_pushvalue(L, 5); // function lua_pushnumber(L, i); // index lua_pushvalue(L, -3); // name lua_call(L, 2, 1); // function returns label luaL_argcheck(L, lua_isstring(L, -1), 5, "function does not return string"); } else lua_pushvalue(L, -1); const char *text = lua_tostring(L, -1); GtkWidget *w = 0; if (hascheck) w = gtk_check_menu_item_new_with_label(text); else if (hascolor) w = gtk_image_menu_item_new_with_label(text); else w = gtk_menu_item_new_with_label(text); if (hascheck && !g_strcmp0(item, current)) gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(w), true); gtk_menu_shell_append(GTK_MENU_SHELL(sm), w); g_signal_connect(w, "activate", G_CALLBACK(itemResponse), this); gtk_widget_show(w); Item mitem; mitem.name = g_strdup(name); mitem.itemName = g_strdup(item); mitem.itemIndex = i; mitem.widget = w; items.push_back(mitem); if (hascolor) { gtk_image_menu_item_set_always_show_image(GTK_IMAGE_MENU_ITEM(w), true); lua_pushvalue(L, 6); // function lua_pushnumber(L, i); // index lua_pushvalue(L, -4); // name lua_call(L, 2, 3); // function returns red, green, blue double red = luaL_checknumber(L, -3); double green = luaL_checknumber(L, -2); double blue = luaL_checknumber(L, -1); lua_pop(L, 3); // pop result GtkWidget *im = colorIcon(red, green, blue); gtk_image_menu_item_set_image(GTK_IMAGE_MENU_ITEM(w), im); g_object_unref(im); } lua_pop(L, 2); // item, text } GtkWidget *sme = gtk_menu_item_new_with_label(title); gtk_widget_show(sme); gtk_menu_item_set_submenu(GTK_MENU_ITEM(sme), sm); gtk_menu_shell_append(GTK_MENU_SHELL(iMenu), sme); gtk_widget_show(sme); } return 0; } // -------------------------------------------------------------------- static int menu_constructor(lua_State *L) { GtkWidget *parent = check_winid(L, 1); Menu **m = (Menu **) lua_newuserdata(L, sizeof(Menu *)); *m = 0; luaL_getmetatable(L, "Ipe.menu"); lua_setmetatable(L, -2); *m = new PMenu(parent); return 1; } // -------------------------------------------------------------------- static int ipeui_getColor(lua_State *L) { check_winid(L, 1); const char *title = luaL_checkstring(L, 2); double r = luaL_checknumber(L, 3); double g = luaL_checknumber(L, 4); double b = luaL_checknumber(L, 5); GdkColor color; color.red = int(r * 65535); color.green = int(g * 65535); color.blue = int(b * 65535); GtkWidget *dlg = gtk_color_selection_dialog_new(title); GtkColorSelection *sel = GTK_COLOR_SELECTION(gtk_color_selection_dialog_get_color_selection (GTK_COLOR_SELECTION_DIALOG(dlg))); gtk_color_selection_set_current_color(sel, &color); int result = gtk_dialog_run(GTK_DIALOG(dlg)); if (result == GTK_RESPONSE_OK) { gtk_color_selection_get_current_color(GTK_COLOR_SELECTION(sel), &color); gtk_widget_destroy(dlg); lua_pushnumber(L, color.red / 65535.0); lua_pushnumber(L, color.green / 65535.0); lua_pushnumber(L, color.blue / 65535.0); return 3; } gtk_widget_destroy(dlg); return 0; } // -------------------------------------------------------------------- static int ipeui_fileDialog(lua_State *L) { static const char * const typenames[] = { "open", "save", 0 }; GtkWindow *parent = GTK_WINDOW(check_winid(L, 1)); int type = luaL_checkoption(L, 2, 0, typenames); const char *caption = luaL_checkstring(L, 3); // const char *filter = luaL_checkstring(L, 4); // not used const char *dir = 0; if (!lua_isnoneornil(L, 5)) dir = luaL_checkstring(L, 5); // GTK dialog uses no filters: // const char *selected = 0; // if (!lua_isnoneornil(L, 6)) // selected = luaL_checkstring(L, 6); GtkWidget *dlg = gtk_file_chooser_dialog_new(caption, parent, (type ? GTK_FILE_CHOOSER_ACTION_SAVE : GTK_FILE_CHOOSER_ACTION_OPEN), GTK_STOCK_CANCEL, GTK_RESPONSE_REJECT, GTK_STOCK_OK, GTK_RESPONSE_ACCEPT, NULL); if (dir) gtk_file_chooser_set_current_folder(GTK_FILE_CHOOSER(dlg), dir); int result = gtk_dialog_run(GTK_DIALOG(dlg)); if (result == GTK_RESPONSE_ACCEPT) { char *fn = gtk_file_chooser_get_filename(GTK_FILE_CHOOSER(dlg)); lua_pushstring(L, fn); lua_pushstring(L, "ipe"); g_free(fn); gtk_widget_destroy(dlg); return 2; } gtk_widget_destroy(dlg); return 0; } // -------------------------------------------------------------------- static int ipeui_messageBox(lua_State *L) { static const char * const options[] = { "none", "warning", "information", "question", "critical", 0 }; static const char * const buttontype[] = { "ok", "okcancel", "yesnocancel", "discardcancel", "savediscardcancel", 0 }; GtkWidget *parent = check_winid(L, 1); int type = luaL_checkoption(L, 2, "none", options); const char *text = luaL_checkstring(L, 3); const char *details = 0; if (!lua_isnoneornil(L, 4)) details = luaL_checkstring(L, 4); int buttons = 0; if (lua_isnumber(L, 5)) buttons = luaL_checkint(L, 5); else if (!lua_isnoneornil(L, 5)) buttons = luaL_checkoption(L, 5, 0, buttontype); GtkMessageType t = GTK_MESSAGE_OTHER; switch (type) { case 0: t = GTK_MESSAGE_OTHER; break; case 1: t = GTK_MESSAGE_WARNING; break; case 2: t = GTK_MESSAGE_INFO; break; case 3: t = GTK_MESSAGE_QUESTION; break; case 4: t = GTK_MESSAGE_ERROR; break; default: break; } GtkWidget *dlg = gtk_message_dialog_new(GTK_WINDOW(parent), GTK_DIALOG_MODAL, t, GTK_BUTTONS_NONE, "%s", text); if (details) gtk_message_dialog_format_secondary_text(GTK_MESSAGE_DIALOG(dlg), "%s", details); switch (buttons) { case 0: // "ok" gtk_dialog_add_buttons(GTK_DIALOG(dlg), GTK_STOCK_OK, GTK_RESPONSE_OK, NULL); break; case 1: // "okcancel" gtk_dialog_add_buttons(GTK_DIALOG(dlg), GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL, GTK_STOCK_OK, GTK_RESPONSE_OK, NULL); break; case 2: // "yesnocancel" gtk_dialog_add_buttons(GTK_DIALOG(dlg), GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL, GTK_STOCK_NO, GTK_RESPONSE_NO, GTK_STOCK_YES, GTK_RESPONSE_YES, NULL); break; case 3: // "discardcancel" gtk_dialog_add_buttons(GTK_DIALOG(dlg), GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL, GTK_STOCK_DISCARD, GTK_RESPONSE_NO, NULL); break; case 4: // "savediscardcancel" gtk_dialog_add_buttons(GTK_DIALOG(dlg), GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL, GTK_STOCK_DISCARD, GTK_RESPONSE_NO, GTK_STOCK_SAVE, GTK_RESPONSE_YES, NULL); default: break; } int result = gtk_dialog_run(GTK_DIALOG(dlg)); switch (result) { case GTK_RESPONSE_YES: case GTK_RESPONSE_OK: lua_pushnumber(L, 1); break; case GTK_RESPONSE_NO: lua_pushnumber(L, 0); break; case GTK_RESPONSE_CANCEL: default: lua_pushnumber(L, -1); break; } gtk_widget_destroy(dlg); return 1; } // -------------------------------------------------------------------- class PTimer : public Timer { public: PTimer(lua_State *L0, int lua_object, const char *method); virtual ~PTimer(); virtual int setInterval(lua_State *L); virtual int active(lua_State *L); virtual int start(lua_State *L); virtual int stop(lua_State *L); private: gboolean elapsed(); static gboolean timerCallback(gpointer data); private: guint iTimer; guint iInterval; }; gboolean PTimer::timerCallback(gpointer data) { PTimer *t = (PTimer *) data; return t->elapsed(); } PTimer::PTimer(lua_State *L0, int lua_object, const char *method) : Timer(L0, lua_object, method) { iTimer = 0; iInterval = 0; } PTimer::~PTimer() { if (iTimer != 0) g_source_remove(iTimer); } gboolean PTimer::elapsed() { callLua(); if (iSingleShot) { iTimer = 0; return FALSE; } else return TRUE; } // does not update interval on running timer int PTimer::setInterval(lua_State *L) { int t = luaL_checkint(L, 2); iInterval = t; return 0; } int PTimer::active(lua_State *L) { lua_pushboolean(L, (iTimer != 0)); return 1; } int PTimer::start(lua_State *L) { if (iTimer == 0) { if (iInterval > 3000) iTimer = g_timeout_add_seconds(iInterval / 1000, GSourceFunc(timerCallback), this); else iTimer = g_timeout_add(iInterval, GSourceFunc(timerCallback), this); } return 0; } int PTimer::stop(lua_State *L) { if (iTimer != 0) { g_source_remove(iTimer); iTimer = 0; } return 0; } // -------------------------------------------------------------------- static int timer_constructor(lua_State *L) { luaL_argcheck(L, lua_istable(L, 1), 1, "argument is not a table"); const char *method = luaL_checkstring(L, 2); Timer **t = (Timer **) lua_newuserdata(L, sizeof(Timer *)); *t = 0; luaL_getmetatable(L, "Ipe.timer"); lua_setmetatable(L, -2); // create a table with weak reference to Lua object lua_createtable(L, 1, 1); lua_pushliteral(L, "v"); lua_setfield(L, -2, "__mode"); lua_pushvalue(L, -1); lua_setmetatable(L, -2); lua_pushvalue(L, 1); lua_rawseti(L, -2, 1); int lua_object = luaL_ref(L, LUA_REGISTRYINDEX); *t = new PTimer(L, lua_object, method); return 1; } // -------------------------------------------------------------------- static int ipeui_closeAllWindows(lua_State *L) { luaL_error(L, "'closeAllWindows' is not yet implemented."); return 0; } static int ipeui_wait(lua_State *L) { luaL_error(L, "'WaitDialog' is not yet implemented."); return 0; } // -------------------------------------------------------------------- static int ipeui_setClipboard(lua_State *L) { const char *data = luaL_checkstring(L, 1); GtkClipboard *b = gtk_clipboard_get(GDK_SELECTION_CLIPBOARD); gtk_clipboard_set_text(b, data, -1); return 0; } static int ipeui_clipboard(lua_State *L) { GtkClipboard *b = gtk_clipboard_get(GDK_SELECTION_CLIPBOARD); char *data = gtk_clipboard_wait_for_text(b); if (data) { lua_pushstring(L, data); g_free(data); return 1; } return 0; } static int ipeui_local8bit(lua_State *L) { const char *s = luaL_checkstring(L, 1); gchar *r = g_locale_from_utf8(s, -1, NULL, NULL, NULL); if (r) { lua_pushstring(L, r); g_free(r); return 1; } return 0; } static int ipeui_currentDateTime(lua_State *L) { time_t t = time(NULL); struct tm *tmp = localtime(&t); if (tmp == NULL) return 0; char buf[16]; sprintf(buf, "%04d%02d%02d%02d%02d%02d", 1900 + tmp->tm_year, 1 + tmp->tm_mon, tmp->tm_mday, tmp->tm_hour, tmp->tm_min, tmp->tm_sec); lua_pushstring(L, buf); return 1; } // -------------------------------------------------------------------- static const struct luaL_Reg ipeui_functions[] = { { "Dialog", dialog_constructor }, { "Menu", menu_constructor }, { "Timer", timer_constructor }, { "getColor", ipeui_getColor }, { "fileDialog", ipeui_fileDialog }, { "messageBox", ipeui_messageBox }, { "WaitDialog", ipeui_wait }, { "closeAllWindows", ipeui_closeAllWindows }, { "currentDateTime", ipeui_currentDateTime }, { "setClipboard", ipeui_setClipboard }, { "clipboard", ipeui_clipboard }, { "local8bit", ipeui_local8bit }, { 0, 0}, }; // -------------------------------------------------------------------- int luaopen_ipeui(lua_State *L) { luaL_newlib(L, ipeui_functions); lua_setglobal(L, "ipeui"); luaopen_ipeui_common(L); return 0; } // -------------------------------------------------------------------- ipe-7.1.4/src/ipeui/ipeui_common.h0000644000175000017500000001271012120621776016715 0ustar otfriedotfried// -------------------------------------------------------------------- // Classes common to several platforms // -------------------------------------------------------------------- /* This file is part of the extensible drawing editor Ipe. Copyright (C) 1993-2013 Otfried Cheong Ipe is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. As a special exception, you have permission to link Ipe with the CGAL library and distribute executables, as long as you follow the requirements of the Gnu General Public License in regard to all of the software in the executable aside from CGAL. Ipe 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 General Public License for more details. You should have received a copy of the GNU General Public License along with Ipe; if not, you can find it at "http://www.gnu.org/copyleft/gpl.html", or write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ #ifndef IPEUI_COMMON_H #define IPEUI_COMMON_H extern "C" { #include #include #include } #include #include #include #include #ifdef IPEUI_GTK #include typedef GtkWidget *WINID; #endif #ifdef IPEUI_WIN32 #include typedef HWND WINID; #endif #ifdef IPEUI_QT #include typedef QWidget *WINID; #endif // -------------------------------------------------------------------- extern WINID check_winid(lua_State *L, int i); extern void push_winid(lua_State *L, WINID win); // -------------------------------------------------------------------- class String { public: String(); explicit String(const char *str); String(const String &rhs); String &operator=(const String &rhs); ~String(); int len() const { return iImp ? strlen(iImp->iData) : 0; } const char *z() const { return iImp ? iImp->iData : ""; } private: struct Imp { int iRefCount; char *iData; }; Imp *iImp; }; // -------------------------------------------------------------------- class Dialog { public: Dialog(lua_State *L0, WINID parent, const char *caption); virtual ~Dialog(); // Lua methods int add(lua_State *L); int addButton(lua_State *L); int set(lua_State *L); int get(lua_State *L); int setEnabled(lua_State *L); int setStretch(lua_State *L); bool execute(lua_State *L, int w, int h); protected: enum TFlags { ELogFile = 0x001, EXml = 0x002, ELatex = 0x040, EAccept = 0x004, EReject = 0x008, EReadOnly = 0x010, EDisabled = 0x020, }; enum TType { EButton = 0, ETextEdit, EList, ELabel, ECombo, ECheckBox, EInput }; struct SElement { String name; TType type; int row, col, rowspan, colspan; int minWidth, minHeight; int lua_method; int flags; std::vector items; String text; int value; }; void callLua(int luaMethod); int findElement(lua_State *L, int index); void setUnmapped(lua_State *L, int idx); virtual void setMapped(lua_State *L, int idx) = 0; virtual bool buildAndRun(int w, int h) = 0; virtual void retrieveValues() = 0; virtual void enableItem(int idx, bool value) = 0; void addButtonItem(lua_State *L, SElement &m); void addTextEdit(lua_State *L, SElement &m); void addList(lua_State *L, SElement &m); void addLabel(lua_State *L, SElement &m); void addCombo(lua_State *L, SElement &m); void addCheckbox(lua_State *L, SElement &m); void addInput(lua_State *L, SElement &m); void setListItems(lua_State *L, int index, SElement &m); protected: lua_State *L; WINID iParent; WINID hDialog; String iCaption; std::vector iElements; int iLuaDialog; bool iIgnoreEscape; int iBaseX, iBaseY; int iNoRows, iNoCols; std::vector iRowStretch; std::vector iColStretch; }; // -------------------------------------------------------------------- inline Dialog **check_dialog(lua_State *L, int i) { return (Dialog **) luaL_checkudata(L, i, "Ipe.dialog"); } // -------------------------------------------------------------------- class Menu { public: virtual ~Menu(); virtual int add(lua_State *L) = 0; virtual int execute(lua_State *L) = 0; }; // -------------------------------------------------------------------- inline Menu **check_menu(lua_State *L, int i) { return (Menu **) luaL_checkudata(L, i, "Ipe.menu"); } // -------------------------------------------------------------------- class Timer { public: Timer(lua_State *L0, int lua_object, const char *method); virtual ~Timer(); int setSingleShot(lua_State *L); virtual int setInterval(lua_State *L) = 0; virtual int active(lua_State *L) = 0; virtual int start(lua_State *L) = 0; virtual int stop(lua_State *L) = 0; protected: void callLua(); protected: lua_State *L; int iLuaObject; String iMethod; bool iSingleShot; }; // -------------------------------------------------------------------- inline Timer **check_timer(lua_State *L, int i) { return (Timer **) luaL_checkudata(L, i, "Ipe.timer"); } // -------------------------------------------------------------------- extern int luaopen_ipeui_common(lua_State *L); // -------------------------------------------------------------------- #endif ipe-7.1.4/src/ipeui/ipeui_win.cpp0000644000175000017500000006746712120621776016600 0ustar otfriedotfried// -------------------------------------------------------------------- // Lua bindings for Win32 dialogs // -------------------------------------------------------------------- /* This file is part of the extensible drawing editor Ipe. Copyright (C) 1993-2013 Otfried Cheong Ipe is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. As a special exception, you have permission to link Ipe with the CGAL library and distribute executables, as long as you follow the requirements of the Gnu General Public License in regard to all of the software in the executable aside from CGAL. Ipe 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 General Public License for more details. You should have received a copy of the GNU General Public License along with Ipe; if not, you can find it at "http://www.gnu.org/copyleft/gpl.html", or write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ #include "ipeui_common.h" #include // -------------------------------------------------------------------- #define IDBASE 9000 #define PAD 4 #define BORDER 8 #define BUTTONHEIGHT 16 class PDialog : public Dialog { public: PDialog(lua_State *L0, WINID parent, const char *caption); virtual ~PDialog(); protected: virtual void setMapped(lua_State *L, int idx); virtual bool buildAndRun(int w, int h); virtual void retrieveValues(); virtual void enableItem(int idx, bool value); void computeDimensions(int &w, int &h); void buildFlags(std::vector &t, DWORD flags); void buildString(std::vector &t, const char *s); void buildDimensions(std::vector &t, SElement &m, int id); void buildControl(std::vector &t, short what, const char *s = 0); void initDialog(); BOOL dlgCommand(WPARAM wParam, LPARAM lParam); static BOOL CALLBACK dialogProc(HWND hwndDlg, UINT message, WPARAM wParam, LPARAM lParam); private: int iBaseX, iBaseY; int iButtonX; std::vector iRowHeight; std::vector iColWidth; }; PDialog::PDialog(lua_State *L0, WINID parent, const char *caption) : Dialog(L0, parent, caption) { LONG base = GetDialogBaseUnits(); iBaseX = LOWORD(base); iBaseY = HIWORD(base); // TODO: handle "Ctrl+Return" } PDialog::~PDialog() { // nothing yet } void PDialog::setMapped(lua_State *L, int idx) { SElement &m = iElements[idx]; HWND h = GetDlgItem(hDialog, idx+IDBASE); switch (m.type) { case ETextEdit: case EInput: case ELabel: SetWindowText(h, m.text.z()); break; case EList: if (!lua_isnumber(L, 3)) { ListBox_ResetContent(h); for (int j = 0; j < int(m.items.size()); ++j) ListBox_AddString(h, m.items[j].z()); } ListBox_SetCurSel(h, m.value); break; case ECombo: if (!lua_isnumber(L, 3)) { ComboBox_ResetContent(h); for (int j = 0; j < int(m.items.size()); ++j) ComboBox_AddString(h, m.items[j].z()); } ComboBox_SetCurSel(h, m.value); break; case ECheckBox: CheckDlgButton(hDialog, idx+IDBASE, (m.value ? BST_CHECKED : BST_UNCHECKED)); break; default: break; // already handled in setUnmapped } } void PDialog::initDialog() { for (int i = 0; i < int(iElements.size()); ++i) { SElement &m = iElements[i]; HWND h = GetDlgItem(hDialog, i+IDBASE); if (m.flags & EDisabled) EnableWindow(h, FALSE); switch (m.type) { case EInput: case ETextEdit: SetWindowText(h, m.text.z()); break; case EList: for (int j = 0; j < int(m.items.size()); ++j) ListBox_AddString(h, m.items[j].z()); ListBox_SetCurSel(h, m.value); break; case ECombo: for (int j = 0; j < int(m.items.size()); ++j) ComboBox_AddString(h, m.items[j].z()); ComboBox_SetCurSel(h, m.value); break; case ECheckBox: CheckDlgButton(hDialog, i+IDBASE, (m.value ? BST_CHECKED : BST_UNCHECKED)); break; default: break; } } } static String getEditText(HWND h) { int n = Edit_GetTextLength(h); if (n == 0) return String(""); char buf[n+1]; Edit_GetText(h, buf, n+1); return String(buf); } void PDialog::retrieveValues() { for (int i = 0; i < int(iElements.size()); ++i) { SElement &m = iElements[i]; HWND h = GetDlgItem(hDialog, i+IDBASE); switch (m.type) { case ETextEdit: case EInput: m.text = getEditText(h); break; case EList: m.value = ListBox_GetCurSel(h); if (m.value == LB_ERR) m.value = 0; break; case ECombo: m.value = ComboBox_GetCurSel(h); if (m.value == CB_ERR) m.value = 0; break; case ECheckBox: m.value = (IsDlgButtonChecked(hDialog, i+IDBASE) == BST_CHECKED); break; case ELabel: default: break; // nothing to do } } } void PDialog::buildFlags(std::vector &t, DWORD flags) { union { DWORD dw; short s[2]; } a; a.dw = flags; t.push_back(a.s[0]); t.push_back(a.s[1]); t.push_back(0); t.push_back(0); } void PDialog::buildDimensions(std::vector &t, SElement &m, int id) { int x = BORDER; int y = BORDER; int w = 0; int h = 0; if (m.row < 0) { y = BORDER; for (int i = 0; i < iNoRows; ++i) y += iRowHeight[i] + PAD; w = m.minWidth; h = BUTTONHEIGHT; x = iButtonX - w; iButtonX -= w + PAD; } else { for (int i = 0; i < m.col; ++i) x += iColWidth[i] + PAD; for (int i = 0; i < m.row; ++i) y += iRowHeight[i] + PAD; w = iColWidth[m.col]; for (int i = m.col + 1; i < m.col + m.colspan; ++i) w += iColWidth[i] + PAD; h = iRowHeight[m.row]; for (int i = m.row + 1; i < m.row + m.rowspan; ++i) h += iRowHeight[i] + PAD; } t.push_back(x); t.push_back(y); t.push_back(w); t.push_back(h); t.push_back(id); // control id } void PDialog::buildString(std::vector &t, const char *s) { int rw = MultiByteToWideChar(CP_UTF8, 0, s, -1, NULL, 0); wchar_t wide[rw]; MultiByteToWideChar(CP_UTF8, 0, s, -1, wide, rw); for (int i = 0; i < rw; ++i) t.push_back(wide[i]); } void PDialog::buildControl(std::vector &t, short what, const char *s) { t.push_back(0xffff); t.push_back(what); if (s) buildString(t, s); else t.push_back(0); // text t.push_back(0); // creation data } BOOL PDialog::dlgCommand(WPARAM wParam, LPARAM lParam) { int id = LOWORD(wParam); if (id == IDOK) { retrieveValues(); EndDialog(hDialog, TRUE); return TRUE; } if (id == IDCANCEL && !iIgnoreEscape) { retrieveValues(); EndDialog(hDialog, FALSE); return TRUE; } if (id < IDBASE || id >= IDBASE + int(iElements.size())) return FALSE; SElement &m = iElements[id - IDBASE]; if (m.flags & EAccept) { retrieveValues(); EndDialog(hDialog, TRUE); return TRUE; } else if (m.flags & EReject) { retrieveValues(); EndDialog(hDialog, FALSE); return TRUE; } else if (m.lua_method != LUA_NOREF) callLua(m.lua_method); return FALSE; } static WNDPROC wpOrigProc; static LRESULT subclassProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) { if (message == WM_KEYDOWN) { if (wParam == VK_RETURN && GetKeyState(VK_CONTROL)) { SendMessage(GetParent(hwnd), WM_COMMAND, IDOK, 0); return 0; } } return CallWindowProc(wpOrigProc, hwnd, message, wParam, lParam); } BOOL CALLBACK PDialog::dialogProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) { PDialog *d = (PDialog *) GetWindowLongPtr(hwnd, GWLP_USERDATA); switch (message) { case WM_INITDIALOG: d = (PDialog *) lParam; SetWindowLongPtr(hwnd, GWLP_USERDATA, (LONG_PTR) d); d->hDialog = hwnd; d->initDialog(); // subclass all Edit controls for (int i = 0; i < int(d->iElements.size()); ++i) { if (d->iElements[i].type == ETextEdit) wpOrigProc = (WNDPROC) SetWindowLong(GetDlgItem(hwnd, i + IDBASE), GWL_WNDPROC, (LONG) subclassProc); } return TRUE; case WM_COMMAND: if (d) return d->dlgCommand(wParam, lParam); else return FALSE; case WM_DESTROY: // Remove the subclasses from text edits for (int i = 0; i < int(d->iElements.size()); ++i) { if (d->iElements[i].type == ETextEdit) SetWindowLong(GetDlgItem(hwnd, i + IDBASE), GWL_WNDPROC, (LONG) wpOrigProc); } return FALSE; default: return FALSE; } } bool PDialog::buildAndRun(int w, int h) { computeDimensions(w, h); RECT rect; GetWindowRect(iParent, &rect); int pw = (rect.right - rect.left) * 4 / iBaseX; int ph = (rect.bottom - rect.top) * 8 / iBaseY; std::vector t; // Dialog flags buildFlags(t, WS_POPUP | WS_BORDER | WS_SYSMENU | DS_MODALFRAME | WS_CAPTION); t.push_back(iElements.size()); t.push_back((pw - w)/2); // offset of popup-window from parent window t.push_back((ph - h)/2); t.push_back(w); t.push_back(h); // menu t.push_back(0); // class t.push_back(0); // title buildString(t, iCaption.z()); // add elements for (int i = 0; i < int(iElements.size()); ++i) { if (t.size() % 2 != 0) t.push_back(0); SElement &m = iElements[i]; int id = i + IDBASE; DWORD flags = WS_CHILD|WS_VISIBLE; switch (m.type) { case EButton: flags |= BS_TEXT|WS_TABSTOP; if (m.flags & EAccept) flags |= BS_DEFPUSHBUTTON; else flags |= BS_PUSHBUTTON; buildFlags(t, flags); buildDimensions(t, m, id); buildControl(t, 0x0080, m.text.z()); // button break; case ECheckBox: buildFlags(t, flags|BS_AUTOCHECKBOX|BS_TEXT|WS_TABSTOP); buildDimensions(t, m, id); buildControl(t, 0x0080, m.text.z()); // button break; case ELabel: buildFlags(t, flags|SS_LEFT); buildDimensions(t, m, id); buildControl(t, 0x0082, m.text.z()); // static text break; case EInput: buildFlags(t, flags|ES_LEFT|WS_TABSTOP|WS_BORDER|ES_AUTOHSCROLL); buildDimensions(t, m, id); buildControl(t, 0x0081); // edit break; case ETextEdit: flags |= ES_LEFT|WS_TABSTOP|WS_BORDER; flags |= ES_MULTILINE|ES_WANTRETURN|WS_VSCROLL; if (m.flags & EReadOnly) flags |= ES_READONLY; buildFlags(t, flags); buildDimensions(t, m, id); buildControl(t, 0x0081); // edit break; case EList: buildFlags(t, flags|WS_TABSTOP|WS_VSCROLL|WS_BORDER); buildDimensions(t, m, id); buildControl(t, 0x0083); // list box break; case ECombo: buildFlags(t, flags|CBS_DROPDOWNLIST|WS_TABSTOP); buildDimensions(t, m, id); buildControl(t, 0x0085); // combo box break; default: break; } } int res = DialogBoxIndirectParam((HINSTANCE) GetWindowLong(iParent, GWL_HINSTANCE), (LPCDLGTEMPLATE) &t[0], iParent, dialogProc, (LPARAM) this); // retrieveValues() has been called before EndDialog! hDialog = NULL; // already destroyed by Windows return (res > 0); } void PDialog::computeDimensions(int &w, int &h) { int minWidth[iNoCols]; int minHeight[iNoRows]; for (int i = 0; i < iNoCols; ++i) minWidth[i] = 0; for (int i = 0; i < iNoRows; ++i) minHeight[i] = 0; int buttonWidth = -PAD; for (int i = 0; i < int(iElements.size()); ++i) { SElement &m = iElements[i]; if (m.row < 0) { // button row buttonWidth += m.minWidth + PAD; } else { int wd = m.minWidth / m.colspan; for (int j = m.col; j < m.col + m.colspan; ++j) { if (wd > minWidth[j]) minWidth[j] = wd; } int ht = m.minHeight / m.rowspan; for (int j = m.row; j < m.row + m.rowspan; ++j) { if (ht > minHeight[j]) minHeight[j] = ht; } } } // Convert w and h to dialog units: w = w * 4 / iBaseX; h = h * 8 / iBaseY; while (int(iColStretch.size()) < iNoCols) iColStretch.push_back(0); while (int(iRowStretch.size()) < iNoRows) iRowStretch.push_back(0); int totalW = BORDER + BORDER - PAD; int totalWStretch = 0; for (int i = 0; i < iNoCols; ++i) { totalW += minWidth[i] + PAD; totalWStretch += iColStretch[i]; } int totalH = BORDER + BORDER + BUTTONHEIGHT; int totalHStretch = 0; for (int i = 0; i < iNoRows; ++i) { totalH += minHeight[i] + PAD; totalHStretch += iRowStretch[i]; } if (totalW > w) w = totalW; if (totalH > h) h = totalH; if (buttonWidth + BORDER + BORDER > w) w = buttonWidth + BORDER + BORDER; iButtonX = w - (w - buttonWidth) / 2; int spareW = w - totalW; int spareH = h - totalH; iColWidth.resize(iNoCols); iRowHeight.resize(iNoRows); if (totalWStretch == 0) { // spread spareW equally int extra = spareW / iNoCols; for (int i = 0; i < iNoCols; ++i) iColWidth[i] = minWidth[i] + extra; } else { for (int i = 0; i < iNoCols; ++i) { int extra = spareW * iColStretch[i] / totalWStretch; iColWidth[i] = minWidth[i] + extra; } } if (totalHStretch == 0) { // spread spareH equally int extra = spareH / iNoRows; for (int i = 0; i < iNoRows; ++i) iRowHeight[i] = minHeight[i] + extra; } else { for (int i = 0; i < iNoRows; ++i) { int extra = spareH * iRowStretch[i] / totalHStretch; iRowHeight[i] = minHeight[i] + extra; } } } void PDialog::enableItem(int idx, bool value) { EnableWindow(GetDlgItem(hDialog, idx+IDBASE), value); } // -------------------------------------------------------------------- static int dialog_constructor(lua_State *L) { HWND parent = check_winid(L, 1); const char *s = luaL_checkstring(L, 2); Dialog **dlg = (Dialog **) lua_newuserdata(L, sizeof(Dialog *)); *dlg = 0; luaL_getmetatable(L, "Ipe.dialog"); lua_setmetatable(L, -2); *dlg = new PDialog(L, parent, s); return 1; } // -------------------------------------------------------------------- class PMenu : public Menu { public: PMenu(HWND parent); virtual ~PMenu(); virtual int add(lua_State *L); virtual int execute(lua_State *L); private: struct Item { String name; String itemName; int itemIndex; }; std::vector items; int currentId; HMENU hMenu; HWND hwnd; std::vector bitmaps; }; PMenu::PMenu(HWND parent) { hMenu = CreatePopupMenu(); hwnd = parent; } PMenu::~PMenu() { if (hMenu) DestroyMenu(hMenu); hMenu = 0; for (int i = 0; i < int(bitmaps.size()); ++i) DeleteObject(bitmaps[i]); } int PMenu::execute(lua_State *L) { int vx = luaL_checkint(L, 2); int vy = luaL_checkint(L, 3); int result = TrackPopupMenu(hMenu, TPM_NONOTIFY | TPM_RETURNCMD | TPM_RIGHTBUTTON, vx, vy, 0, hwnd, NULL); if (1 <= result && result <= int(items.size())) { result -= 1; lua_pushstring(L, items[result].name.z()); lua_pushinteger(L, items[result].itemIndex); if (items[result].itemName.z()) lua_pushstring(L, items[result].itemName.z()); else lua_pushstring(L, ""); return 3; } return 0; } static HBITMAP colorIcon(double red, double green, double blue) { int r = int(red * 255.0); int g = int(green * 255.0); int b = int(blue * 255.0); COLORREF rgb = RGB(r, g, b); int cx = GetSystemMetrics(SM_CXMENUCHECK); int cy = GetSystemMetrics(SM_CYMENUCHECK); HDC hdc = GetDC(NULL); HDC memDC = CreateCompatibleDC(hdc); HBITMAP bm = CreateCompatibleBitmap(hdc, cx, cy); SelectObject(memDC, bm); for (int y = 0; y < cy; ++y) { for (int x = 0; x < cx; ++x) { SetPixel(memDC, x, y, rgb); } } DeleteDC(memDC); ReleaseDC(NULL, hdc); return bm; } int PMenu::add(lua_State *L) { const char *name = luaL_checkstring(L, 2); const char *title = luaL_checkstring(L, 3); if (lua_gettop(L) == 3) { AppendMenu(hMenu, MF_STRING, items.size() + 1, title); Item item; item.name = String(name); item.itemIndex = 0; items.push_back(item); } else { luaL_argcheck(L, lua_istable(L, 4), 4, "argument is not a table"); bool hasmap = !lua_isnoneornil(L, 5) && lua_isfunction(L, 5); bool hastable = !hasmap && !lua_isnoneornil(L, 5); bool hascolor = !lua_isnoneornil(L, 6) && lua_isfunction(L, 6); bool hascheck = !hascolor && !lua_isnoneornil(L, 6); if (hastable) luaL_argcheck(L, lua_istable(L, 5), 5, "argument is not a function or table"); const char *current = 0; if (hascheck) { luaL_argcheck(L, lua_isstring(L, 6), 6, "argument is not a function or string"); current = luaL_checkstring(L, 6); } int no = lua_objlen(L, 4); HMENU sm = CreatePopupMenu(); for (int i = 1; i <= no; ++i) { lua_rawgeti(L, 4, i); luaL_argcheck(L, lua_isstring(L, -1), 4, "items must be strings"); int id = items.size() + 1; const char *item = lua_tostring(L, -1); if (hastable) { lua_rawgeti(L, 5, i); luaL_argcheck(L, lua_isstring(L, -1), 5, "labels must be strings"); } else if (hasmap) { lua_pushvalue(L, 5); // function lua_pushnumber(L, i); // index lua_pushvalue(L, -3); // name lua_call(L, 2, 1); // function returns label luaL_argcheck(L, lua_isstring(L, -1), 5, "function does not return string"); } else lua_pushvalue(L, -1); const char *text = lua_tostring(L, -1); AppendMenu(sm, MF_STRING, id, text); Item mitem; mitem.name = String(name); mitem.itemName = String(item); mitem.itemIndex = i; items.push_back(mitem); if (hascheck && !strcmp(item, current)) CheckMenuItem(sm, id, MF_CHECKED); if (hascolor) { lua_pushvalue(L, 6); // function lua_pushnumber(L, i); // index lua_pushvalue(L, -4); // name lua_call(L, 2, 3); // function returns red, green, blue double red = luaL_checknumber(L, -3); double green = luaL_checknumber(L, -2); double blue = luaL_checknumber(L, -1); lua_pop(L, 3); // pop result HBITMAP bits = colorIcon(red, green, blue); bitmaps.push_back(bits); SetMenuItemBitmaps(sm, id, MF_BYCOMMAND, bits, bits); } lua_pop(L, 2); // item, text } AppendMenu(hMenu, MF_STRING | MF_POPUP, UINT(sm), title); } return 0; } // -------------------------------------------------------------------- static int menu_constructor(lua_State *L) { HWND hwnd = check_winid(L, 1); Menu **m = (Menu **) lua_newuserdata(L, sizeof(Menu *)); *m = 0; luaL_getmetatable(L, "Ipe.menu"); lua_setmetatable(L, -2); *m = new PMenu(hwnd); return 1; } // -------------------------------------------------------------------- class PTimer : public Timer { public: PTimer(lua_State *L0, int lua_object, const char *method); virtual ~PTimer(); virtual int setInterval(lua_State *L); virtual int active(lua_State *L); virtual int start(lua_State *L); virtual int stop(lua_State *L); protected: void elapsed(); static void CALLBACK TimerProc(HWND hwnd, UINT uMsg, UINT_PTR idEvent, DWORD dwTime); static std::vector all_timers; protected: UINT_PTR iTimer; UINT iInterval; }; std::vector PTimer::all_timers; void CALLBACK PTimer::TimerProc(HWND, UINT, UINT_PTR id, DWORD) { for (int i = 0; i < int(all_timers.size()); ++i) { if (id == all_timers[i]->iTimer) { all_timers[i]->elapsed(); return; } } } PTimer::PTimer(lua_State *L0, int lua_object, const char *method) : Timer(L0, lua_object, method) { iTimer = 0; iInterval = 0; all_timers.push_back(this); } PTimer::~PTimer() { if (iTimer) KillTimer(NULL, iTimer); // remove it from all_timers for (int i = 0; i < int(all_timers.size()); ++i) { if (all_timers[i] == this) { all_timers.erase(all_timers.begin() + i); return; } } } void PTimer::elapsed() { callLua(); if (iSingleShot) { KillTimer(NULL, iTimer); iTimer = 0; } } int PTimer::setInterval(lua_State *L) { int t = luaL_checkint(L, 2); iInterval = t; if (iTimer) SetTimer(NULL, iTimer, iInterval, TimerProc); return 0; } int PTimer::active(lua_State *L) { lua_pushboolean(L, (iTimer != 0)); return 1; } int PTimer::start(lua_State *L) { if (iTimer == 0) iTimer = SetTimer(NULL, 0, iInterval, TimerProc); return 0; } int PTimer::stop(lua_State *L) { if (iTimer) { KillTimer(NULL, iTimer); iTimer = 0; } return 0; } // -------------------------------------------------------------------- static int timer_constructor(lua_State *L) { luaL_argcheck(L, lua_istable(L, 1), 1, "argument is not a table"); const char *method = luaL_checkstring(L, 2); Timer **t = (Timer **) lua_newuserdata(L, sizeof(Timer *)); *t = 0; luaL_getmetatable(L, "Ipe.timer"); lua_setmetatable(L, -2); // create a table with weak reference to Lua object lua_createtable(L, 1, 1); lua_pushliteral(L, "v"); lua_setfield(L, -2, "__mode"); lua_pushvalue(L, -1); lua_setmetatable(L, -2); lua_pushvalue(L, 1); lua_rawseti(L, -2, 1); int lua_object = luaL_ref(L, LUA_REGISTRYINDEX); *t = new PTimer(L, lua_object, method); return 1; } // -------------------------------------------------------------------- static COLORREF custom[16] = { 0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff }; static int ipeui_getColor(lua_State *L) { HWND hwnd = check_winid(L, 1); // const char *title = luaL_checkstring(L, 2); double r = luaL_checknumber(L, 3); double g = luaL_checknumber(L, 4); double b = luaL_checknumber(L, 5); CHOOSECOLOR cc; ZeroMemory(&cc, sizeof(cc)); cc.lStructSize = sizeof(cc); cc.hwndOwner = hwnd; cc.Flags = CC_FULLOPEN | CC_RGBINIT; cc.rgbResult = RGB(int(r * 255), int(g * 255), int(b * 255)); cc.lpCustColors = custom; if (ChooseColor(&cc)) { lua_pushnumber(L, GetRValue(cc.rgbResult) / 255.0); lua_pushnumber(L, GetGValue(cc.rgbResult) / 255.0); lua_pushnumber(L, GetBValue(cc.rgbResult) / 255.0); return 3; } else return 0; } // -------------------------------------------------------------------- static int ipeui_fileDialog(lua_State *L) { static const char * const typenames[] = { "open", "save", 0 }; HWND hwnd = check_winid(L, 1); int type = luaL_checkoption(L, 2, 0, typenames); const char *caption = luaL_checkstring(L, 3); // const char *filter = luaL_checkstring(L, 4); const char *dir = 0; if (!lua_isnoneornil(L, 5)) dir = luaL_checkstring(L, 5); // const char *selected = 0; // if (!lua_isnoneornil(L, 6)) // selected = luaL_checkstring(L, 6); OPENFILENAME ofn; char szFileName[MAX_PATH] = ""; ZeroMemory(&ofn, sizeof(ofn)); ofn.lStructSize = sizeof(ofn); ofn.hwndOwner = hwnd; // TODO! ofn.lpstrFilter = "Ipe Files\0*.ipe;*.pdf;*.eps\0All Files\0*.*\0"; ofn.nFilterIndex = 1; ofn.lpstrFile = szFileName; ofn.nMaxFile = MAX_PATH; ofn.lpstrDefExt = "ipe"; ofn.lpstrInitialDir = dir; ofn.lpstrTitle = caption; if (type == 0) { ofn.Flags = OFN_EXPLORER | OFN_FILEMUSTEXIST | OFN_HIDEREADONLY; if (GetOpenFileName(&ofn)) { lua_pushstring(L, ofn.lpstrFile); lua_pushstring(L, "ipe"); return 2; } } else { ofn.Flags = OFN_EXPLORER | OFN_PATHMUSTEXIST | OFN_HIDEREADONLY; if (GetSaveFileName(&ofn)) { lua_pushstring(L, ofn.lpstrFile); lua_pushstring(L, "ipe"); return 2; } } return 0; } // -------------------------------------------------------------------- static int ipeui_messageBox(lua_State *L) { static const char * const options[] = { "none", "warning", "information", "question", "critical", 0 }; static const char * const buttontype[] = { "ok", "okcancel", "yesnocancel", "discardcancel", "savediscardcancel", 0 }; HWND hwnd = check_winid(L, 1); int type = luaL_checkoption(L, 2, "none", options); const char *text = luaL_checkstring(L, 3); const char *details = 0; if (!lua_isnoneornil(L, 4)) details = luaL_checkstring(L, 4); int buttons = 0; if (lua_isnumber(L, 5)) buttons = luaL_checkint(L, 5); else if (!lua_isnoneornil(L, 5)) buttons = luaL_checkoption(L, 5, 0, buttontype); UINT uType = MB_APPLMODAL; switch (type) { case 0: default: break; case 1: uType |= MB_ICONWARNING; break; case 2: uType |= MB_ICONINFORMATION; break; case 3: uType |= MB_ICONQUESTION; break; case 4: uType |= MB_ICONERROR; break; } switch (buttons) { case 0: default: uType |= MB_OK; break; case 1: uType |= MB_OKCANCEL; break; case 2: uType |= MB_YESNOCANCEL; break; case 3: uType |= MB_OKCANCEL; // TODO should be Discard Cancel break; case 4: uType |= MB_YESNOCANCEL; // TODO should be Save Discard Cancel break; } int ret = -1; if (details) { char buf[strlen(text) + strlen(details) + 8]; sprintf(buf, "%s\n\n%s", text, details); ret = MessageBox(hwnd, buf, "Ipe", uType); } else ret = MessageBox(hwnd, text, "Ipe", uType); switch (ret) { case IDOK: case IDYES: lua_pushnumber(L, 1); break; case IDNO: case IDIGNORE: lua_pushnumber(L, 0); break; case IDCANCEL: default: lua_pushnumber(L, -1); break; } return 1; } // -------------------------------------------------------------------- static int ipeui_wait(lua_State *L) { luaL_error(L, "'WaitDialog' is not implemented on Windows."); return 0; } static int ipeui_closeAllWindows(lua_State *L) { luaL_error(L, "'closeAllWindows' is not implemented on Windows."); return 0; } // -------------------------------------------------------------------- static int ipeui_setClipboard(lua_State *L) { const char *data = luaL_checkstring(L, 1); int l = strlen(data); GLOBALHANDLE hGlobal = GlobalAlloc(GHND | GMEM_SHARE, l + 1); char *p = (char *) GlobalLock(hGlobal); for (int i = 0; i < l; ++i) *p++ = *data++; GlobalUnlock(hGlobal); OpenClipboard(NULL); // hwnd! EmptyClipboard(); SetClipboardData(CF_TEXT, hGlobal); CloseClipboard(); return 0; } static int ipeui_clipboard(lua_State *L) { OpenClipboard(NULL); // hwnd! GLOBALHANDLE hGlobal = GetClipboardData(CF_TEXT); if (hGlobal == NULL) return 0; char *q = (char *) GlobalLock(hGlobal); lua_pushstring(L, q); // this makes a copy! GlobalUnlock(hGlobal); CloseClipboard(); return 1; } static int ipeui_local8bit(lua_State *L) { const char *in = luaL_checkstring(L, 1); int rw = MultiByteToWideChar(CP_UTF8, 0, in, -1, NULL, 0); wchar_t wide[rw]; MultiByteToWideChar(CP_UTF8, 0, in, -1, wide, rw); int rm = WideCharToMultiByte(CP_ACP, 0, wide, -1, NULL, 0, NULL, NULL); char multi[rm]; WideCharToMultiByte(CP_ACP, 0, wide, -1, multi, rm, NULL, NULL); lua_pushstring(L, multi); return 1; } static int ipeui_currentDateTime(lua_State *L) { SYSTEMTIME st; GetLocalTime(&st); char buf[16]; sprintf(buf, "%04d%02d%02d%02d%02d%02d", st.wYear, st.wMonth, st.wDay, st.wHour, st.wMinute, st.wSecond); lua_pushstring(L, buf); return 1; } static int ipeui_startBrowser(lua_State *L) { const char *url = luaL_checkstring(L, 1); ShellExecuteA(0, "open", url, 0, 0, 0); return 0; } // -------------------------------------------------------------------- static const struct luaL_Reg ipeui_functions[] = { { "Dialog", dialog_constructor }, { "Menu", menu_constructor }, { "Timer", timer_constructor }, { "getColor", ipeui_getColor }, { "fileDialog", ipeui_fileDialog }, { "messageBox", ipeui_messageBox }, { "WaitDialog", ipeui_wait }, { "closeAllWindows", ipeui_closeAllWindows }, { "currentDateTime", ipeui_currentDateTime }, { "setClipboard", ipeui_setClipboard }, { "clipboard", ipeui_clipboard }, { "local8bit", ipeui_local8bit }, { "startBrowser", ipeui_startBrowser }, { 0, 0}, }; // -------------------------------------------------------------------- int luaopen_ipeui(lua_State *L) { luaL_register(L, "ipeui", ipeui_functions); luaopen_ipeui_common(L); return 0; } // -------------------------------------------------------------------- ipe-7.1.4/src/iperender/0000755000175000017500000000000012120621776014722 5ustar otfriedotfriedipe-7.1.4/src/iperender/Makefile0000644000175000017500000000142512120621776016364 0ustar otfriedotfried# -------------------------------------------------------------------- # Makefile for Iperender # -------------------------------------------------------------------- OBJDIR = $(BUILDDIR)/obj/iperender include ../common.mak TARGET = $(call exe_target,iperender) CPPFLAGS += -I../include $(CAIRO_CFLAGS) -I../ipecairo LIBS += -L$(buildlib) -lipecairo -lipe $(CAIRO_LIBS) all: $(TARGET) sources = iperender.cpp $(TARGET): $(objects) $(MAKE_BINDIR) $(CXX) $(LDFLAGS) -o $@ $^ $(LIBS) clean: @-rm -f $(objects) $(TARGET) $(DEPEND) $(DEPEND): Makefile $(MAKE_DEPEND) -include $(DEPEND) install: $(TARGET) $(INSTALL_DIR) $(INSTALL_ROOT)$(IPEBINDIR) $(INSTALL_PROGRAMS) $(TARGET) $(INSTALL_ROOT)$(IPEBINDIR) # -------------------------------------------------------------------- ipe-7.1.4/src/iperender/iperender.cpp0000644000175000017500000001347612120621776017416 0ustar otfriedotfried// -------------------------------------------------------------------- // iperender // -------------------------------------------------------------------- /* This file is part of the extensible drawing editor Ipe. Copyright (C) 1993-2013 Otfried Cheong Ipe is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. As a special exception, you have permission to link Ipe with the CGAL library and distribute executables, as long as you follow the requirements of the Gnu General Public License in regard to all of the software in the executable aside from CGAL. Ipe 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 General Public License for more details. You should have received a copy of the GNU General Public License along with Ipe; if not, you can find it at "http://www.gnu.org/copyleft/gpl.html", or write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ #include "ipeutils.h" #include "ipedoc.h" #include "ipefonts.h" #include "ipecairopainter.h" #include #include #include #include #ifdef CAIRO_HAS_PDF_SURFACE #include #endif #ifdef CAIRO_HAS_PS_SURFACE #include #endif enum TargetFormat { ESVG, EPNG, EPS, EPDF }; using ipe::Document; using ipe::Page; // -------------------------------------------------------------------- static void render(TargetFormat fm, const char *dst, const Document *doc, const Page *page, int view, double zoom, bool transparent) { ipe::Rect bbox = page->pageBBox(doc->cascade()); int wid = int(bbox.width() * zoom + 1); int ht = int(bbox.height() * zoom + 1); ipe::Buffer data; cairo_surface_t* surface = 0; if (fm == EPNG) { data = ipe::Buffer(wid * ht * 4); if (transparent) memset(data.data(), 0x00, wid * ht * 4); else memset(data.data(), 0xff, wid * ht * 4); surface = cairo_image_surface_create_for_data((uchar *) data.data(), CAIRO_FORMAT_ARGB32, wid, ht, wid * 4); } else if (fm == ESVG) { surface = cairo_svg_surface_create(dst, wid, ht); #ifdef CAIRO_HAS_PS_SURFACE } else if (fm == EPS) { surface = cairo_ps_surface_create(dst, wid, ht); #endif #ifdef CAIRO_HAS_PDF_SURFACE } else if (fm == EPDF) { surface = cairo_pdf_surface_create(dst, wid, ht); #endif } cairo_t *cc = cairo_create(surface); cairo_scale(cc, zoom, -zoom); cairo_translate(cc, -bbox.topLeft().x, -bbox.topLeft().y); IpeAutoPtr fonts(ipe::Fonts::New(doc->fontPool())); ipe::CairoPainter painter(doc->cascade(), fonts.ptr(), cc, zoom, true); // painter.Transform(IpeLinear(zoom, 0, 0, -zoom)); // painter.Translate(-bbox.TopLeft()); painter.pushMatrix(); for (int i = 0; i < page->count(); ++i) { if (page->objectVisible(view, i)) page->object(i)->draw(painter); } painter.popMatrix(); cairo_surface_flush(surface); cairo_show_page(cc); if (fm == EPNG) cairo_surface_write_to_png(surface, dst); cairo_destroy(cc); cairo_surface_destroy(surface); } // -------------------------------------------------------------------- static int renderPage(TargetFormat fm, const char *src, const char *dst, int pageNum, int viewNum, double zoom, bool transparent) { Document *doc = Document::loadWithErrorReport(src); if (!doc) return 1; if (pageNum < 1 || pageNum > doc->countPages()) { fprintf(stderr, "The document contains %d pages, cannot convert page %d.\n", doc->countPages(), pageNum); delete doc; return 1; } if (doc->runLatex()) { delete doc; return 1; } const Page *page = doc->page(pageNum - 1); render(fm, dst, doc, page, viewNum - 1, zoom, transparent); delete doc; return 0; } // -------------------------------------------------------------------- static void usage() { fprintf(stderr, "Usage: iperender [ -svg | -png ] " "[ -page ] [ -view ] [ -resolution ] " "infile outfile\n" "Iperender saves a single page of the Ipe document in some formats.\n" " -page : page to save (default 1).\n" " -view : view to save (default 1).\n" " -resolution : resolution for png format (default 72.0 ppi).\n" " -transparent: use transparent background in png format.\n"); exit(1); } int main(int argc, char *argv[]) { ipe::Platform::initLib(ipe::IPELIB_VERSION); // ensure at least three arguments (handles -help as well :-) if (argc < 4) usage(); TargetFormat fm = EPNG; if (!strcmp(argv[1], "-png")) fm = EPNG; #ifdef CAIRO_HAS_PS_SURFACE else if (!strcmp(argv[1], "-ps")) fm = EPS; #endif #ifdef CAIRO_HAS_PDF_SURFACE else if (!strcmp(argv[1], "-pdf")) fm = EPDF; #endif else if (!strcmp(argv[1], "-svg")) fm = ESVG; else usage(); int page = 1; int view = 1; double dpi = 72.0; int i = 2; bool transparent = false; if (!strcmp(argv[i], "-page")) { page = ipe::Lex(ipe::String(argv[i+1])).getInt(); i += 2; } if (!strcmp(argv[i], "-view")) { view = ipe::Lex(ipe::String(argv[i+1])).getInt(); i += 2; } if (!strcmp(argv[i], "-resolution")) { dpi = ipe::Lex(ipe::String(argv[i+1])).getDouble(); i += 2; } if (!strcmp(argv[i], "-transparent")) { transparent = true; ++i; } // remaining arguments must be two filenames if (argc != i + 2) usage(); const char *src = argv[i]; const char *dst = argv[i+1]; return renderPage(fm, src, dst, page, view, dpi / 72.0, transparent); } // -------------------------------------------------------------------- ipe-7.1.4/src/ipecairo/0000755000175000017500000000000012120621776014540 5ustar otfriedotfriedipe-7.1.4/src/ipecairo/ipethumbs.h0000644000175000017500000000354612120621776016721 0ustar otfriedotfried// -*- C++ -*- // -------------------------------------------------------------------- // ipe::Thumbnail // -------------------------------------------------------------------- /* This file is part of the extensible drawing editor Ipe. Copyright (C) 1993-2013 Otfried Cheong Ipe is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. As a special exception, you have permission to link Ipe with the CGAL library and distribute executables, as long as you follow the requirements of the Gnu General Public License in regard to all of the software in the executable aside from CGAL. Ipe 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 General Public License for more details. You should have received a copy of the GNU General Public License along with Ipe; if not, you can find it at "http://www.gnu.org/copyleft/gpl.html", or write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ #ifndef IPETHUMBS_H #define IPETHUMBS_H #include "ipedoc.h" #include "ipefonts.h" // -------------------------------------------------------------------- namespace ipe { class Thumbnail { public: Thumbnail(const Document *doc, int width); ~Thumbnail(); int height() const { return iHeight; } Buffer render(const Page *page, int view); private: const Document *iDoc; int iWidth; int iHeight; double iZoom; const Layout *iLayout; Fonts *iFonts; }; } // namespace // -------------------------------------------------------------------- #endif ipe-7.1.4/src/ipecairo/ipestdfonts.cpp0000644000175000017500000033131412120621776017613 0ustar otfriedotfried// -------------------------------------------------------------------- // Width information for the 14 standard postscript fonts // Taken from Xpdf 2.01, Copyright 2001-2002 Glyph & Cog, LLC // -------------------------------------------------------------------- /* This file is part of the extensible drawing editor Ipe. Copyright (C) 1993-2013 Otfried Cheong Ipe is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. As a special exception, you have permission to link Ipe with the CGAL library and distribute executables, as long as you follow the requirements of the Gnu General Public License in regard to all of the software in the executable aside from CGAL. Ipe 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 General Public License for more details. You should have received a copy of the GNU General Public License along with Ipe; if not, you can find it at "http://www.gnu.org/copyleft/gpl.html", or write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ #include "ipebase.h" using namespace ipe; // -------------------------------------------------------------------- struct StdFontWidth { const char *iName; ushort iWidth; }; struct StdFontData { const char *iName; const StdFontWidth *iWidths; int iNumWidths; short iAscent; short iDescent; short iBBox[4]; }; // -------------------------------------------------------------------- // All courier fonts are monospaced with a width of 600 static const StdFontWidth helveticaWidthsTab[] = { { "Ntilde", 722 }, { "comma", 278 }, { "cedilla", 333 }, { "plusminus", 584 }, { "circumflex", 333 }, { "dotaccent", 333 }, { "asciitilde", 584 }, { "colon", 278 }, { "onehalf", 834 }, { "dollar", 556 }, { "ntilde", 556 }, { "minus", 584 }, { "yen", 556 }, { "space", 278 }, { "questiondown", 611 }, { "emdash", 1000 }, { "Agrave", 667 }, { "three", 556 }, { "numbersign", 556 }, { "A", 667 }, { "B", 667 }, { "C", 722 }, { "D", 722 }, { "E", 667 }, { "onequarter", 834 }, { "F", 611 }, { "G", 778 }, { "H", 722 }, { "I", 278 }, { "J", 500 }, { "K", 667 }, { "backslash", 278 }, { "L", 556 }, { "periodcentered", 278 }, { "M", 833 }, { "N", 722 }, { "O", 778 }, { "P", 667 }, { "Q", 778 }, { "R", 722 }, { "Aacute", 667 }, { "caron", 333 }, { "S", 667 }, { "T", 611 }, { "U", 722 }, { "agrave", 556 }, { "V", 667 }, { "W", 944 }, { "X", 667 }, { "question", 556 }, { "equal", 584 }, { "Y", 667 }, { "Z", 611 }, { "four", 556 }, { "a", 556 }, { "b", 556 }, { "c", 500 }, { "d", 556 }, { "e", 556 }, { "f", 278 }, { "g", 556 }, { "bullet", 350 }, { "h", 556 }, { "i", 222 }, { "Oslash", 778 }, { "dagger", 556 }, { "j", 222 }, { "k", 500 }, { "l", 222 }, { "m", 833 }, { "n", 556 }, { "o", 556 }, { "ordfeminine", 370 }, { "ring", 333 }, { "p", 556 }, { "q", 556 }, { "r", 333 }, { "twosuperior", 333 }, { "aacute", 556 }, { "s", 500 }, { "OE", 1000 }, { "t", 278 }, { "divide", 584 }, { "u", 556 }, { "v", 500 }, { "w", 722 }, { "x", 500 }, { "y", 500 }, { "z", 500 }, { "hungarumlaut", 333 }, { "quotedbl", 355 }, { "mu", 556 }, { "Scaron", 667 }, { "Lslash", 556 }, { "semicolon", 278 }, { "oslash", 611 }, { "parenright", 333 }, { "Ecircumflex", 667 }, { "trademark", 1000 }, { "daggerdbl", 556 }, { "macron", 333 }, { "Otilde", 778 }, { "ellipsis", 1000 }, { "scaron", 500 }, { "AE", 1000 }, { "Ucircumflex", 722 }, { "lslash", 222 }, { "quotedblleft", 333 }, { "guilsinglright", 333 }, { "hyphen", 333 }, { "quotesingle", 191 }, { "eight", 556 }, { "exclamdown", 333 }, { "endash", 556 }, { "oe", 944 }, { "ecircumflex", 556 }, { "copyright", 737 }, { "Adieresis", 667 }, { "Egrave", 667 }, { "slash", 278 }, { "Edieresis", 667 }, { "otilde", 556 }, { "Idieresis", 278 }, { "parenleft", 333 }, { "one", 556 }, { "ucircumflex", 556 }, { "Odieresis", 778 }, { "bracketleft", 278 }, { "Ugrave", 722 }, { "quoteright", 222 }, { "Udieresis", 722 }, { "perthousand", 1000 }, { "Ydieresis", 667 }, { "Eacute", 667 }, { "adieresis", 556 }, { "egrave", 556 }, { "edieresis", 556 }, { "idieresis", 278 }, { "Eth", 722 }, { "ae", 889 }, { "asterisk", 389 }, { "odieresis", 556 }, { "Uacute", 722 }, { "ugrave", 556 }, { "nine", 556 }, { "five", 556 }, { "udieresis", 556 }, { "Zcaron", 611 }, { "threequarters", 834 }, { "guillemotright", 556 }, { "ydieresis", 500 }, { "Ccedilla", 722 }, { "tilde", 333 }, { "at", 1015 }, { "eacute", 556 }, { "underscore", 556 }, { "multiply", 584 }, { "zero", 556 }, { "eth", 556 }, { "Ograve", 778 }, { "uacute", 556 }, { "braceleft", 334 }, { "Thorn", 667 }, { "zcaron", 500 }, { "ccedilla", 500 }, { "Ocircumflex", 778 }, { "Oacute", 778 }, { "ogonek", 333 }, { "ograve", 556 }, { "thorn", 556 }, { "degree", 400 }, { "registered", 737 }, { "Aring", 667 }, { "percent", 889 }, { "six", 556 }, { "paragraph", 537 }, { "two", 556 }, { "Igrave", 278 }, { "ocircumflex", 556 }, { "oacute", 556 }, { "asciicircum", 469 }, { "aring", 556 }, { "grave", 333 }, { "bracketright", 278 }, { "Iacute", 278 }, { "ampersand", 667 }, { "igrave", 278 }, { "plus", 584 }, { "quotesinglbase", 222 }, { "Yacute", 667 }, { "threesuperior", 333 }, { "acute", 333 }, { "section", 556 }, { "dieresis", 333 }, { "iacute", 278 }, { "quotedblbase", 333 }, { "florin", 556 }, { "yacute", 500 }, { "fi", 500 }, { "fl", 500 }, { "Acircumflex", 667 }, { "Icircumflex", 278 }, { "guillemotleft", 556 }, { "germandbls", 611 }, { "seven", 556 }, { "ordmasculine", 365 }, { "dotlessi", 278 }, { "sterling", 556 }, { "acircumflex", 556 }, { "icircumflex", 278 }, { "braceright", 334 }, { "quotedblright", 333 }, { "cent", 556 }, { "currency", 556 }, { "logicalnot", 584 }, { "Atilde", 667 }, { "breve", 333 }, { "bar", 260 }, { "fraction", 167 }, { "less", 584 }, { "guilsinglleft", 333 }, { "exclam", 278 }, { "period", 278 }, { "greater", 584 }, { "atilde", 556 }, { "brokenbar", 260 }, { "quoteleft", 222 }, { "onesuperior", 333 } }; static const StdFontWidth helveticaBoldWidthsTab[] = { { "Ntilde", 722 }, { "comma", 278 }, { "cedilla", 333 }, { "plusminus", 584 }, { "circumflex", 333 }, { "dotaccent", 333 }, { "asciitilde", 584 }, { "colon", 333 }, { "onehalf", 834 }, { "dollar", 556 }, { "ntilde", 611 }, { "minus", 584 }, { "yen", 556 }, { "space", 278 }, { "questiondown", 611 }, { "emdash", 1000 }, { "Agrave", 722 }, { "three", 556 }, { "numbersign", 556 }, { "A", 722 }, { "B", 722 }, { "C", 722 }, { "D", 722 }, { "E", 667 }, { "onequarter", 834 }, { "F", 611 }, { "G", 778 }, { "H", 722 }, { "I", 278 }, { "J", 556 }, { "K", 722 }, { "backslash", 278 }, { "L", 611 }, { "periodcentered", 278 }, { "M", 833 }, { "N", 722 }, { "O", 778 }, { "P", 667 }, { "Q", 778 }, { "R", 722 }, { "Aacute", 722 }, { "caron", 333 }, { "S", 667 }, { "T", 611 }, { "U", 722 }, { "agrave", 556 }, { "V", 667 }, { "W", 944 }, { "X", 667 }, { "question", 611 }, { "equal", 584 }, { "Y", 667 }, { "Z", 611 }, { "four", 556 }, { "a", 556 }, { "b", 611 }, { "c", 556 }, { "d", 611 }, { "e", 556 }, { "f", 333 }, { "g", 611 }, { "bullet", 350 }, { "h", 611 }, { "i", 278 }, { "Oslash", 778 }, { "dagger", 556 }, { "j", 278 }, { "k", 556 }, { "l", 278 }, { "m", 889 }, { "n", 611 }, { "o", 611 }, { "ordfeminine", 370 }, { "ring", 333 }, { "p", 611 }, { "q", 611 }, { "r", 389 }, { "twosuperior", 333 }, { "aacute", 556 }, { "s", 556 }, { "OE", 1000 }, { "t", 333 }, { "divide", 584 }, { "u", 611 }, { "v", 556 }, { "w", 778 }, { "x", 556 }, { "y", 556 }, { "z", 500 }, { "hungarumlaut", 333 }, { "quotedbl", 474 }, { "mu", 611 }, { "Scaron", 667 }, { "Lslash", 611 }, { "semicolon", 333 }, { "oslash", 611 }, { "parenright", 333 }, { "Ecircumflex", 667 }, { "trademark", 1000 }, { "daggerdbl", 556 }, { "macron", 333 }, { "Otilde", 778 }, { "ellipsis", 1000 }, { "scaron", 556 }, { "AE", 1000 }, { "Ucircumflex", 722 }, { "lslash", 278 }, { "quotedblleft", 500 }, { "guilsinglright", 333 }, { "hyphen", 333 }, { "quotesingle", 238 }, { "eight", 556 }, { "exclamdown", 333 }, { "endash", 556 }, { "oe", 944 }, { "ecircumflex", 556 }, { "copyright", 737 }, { "Adieresis", 722 }, { "Egrave", 667 }, { "slash", 278 }, { "Edieresis", 667 }, { "otilde", 611 }, { "Idieresis", 278 }, { "parenleft", 333 }, { "one", 556 }, { "ucircumflex", 611 }, { "Odieresis", 778 }, { "bracketleft", 333 }, { "Ugrave", 722 }, { "quoteright", 278 }, { "Udieresis", 722 }, { "perthousand", 1000 }, { "Ydieresis", 667 }, { "Eacute", 667 }, { "adieresis", 556 }, { "egrave", 556 }, { "edieresis", 556 }, { "idieresis", 278 }, { "Eth", 722 }, { "ae", 889 }, { "asterisk", 389 }, { "odieresis", 611 }, { "Uacute", 722 }, { "ugrave", 611 }, { "nine", 556 }, { "five", 556 }, { "udieresis", 611 }, { "Zcaron", 611 }, { "threequarters", 834 }, { "guillemotright", 556 }, { "ydieresis", 556 }, { "Ccedilla", 722 }, { "tilde", 333 }, { "dbldaggerumlaut", 556 }, { "at", 975 }, { "eacute", 556 }, { "underscore", 556 }, { "multiply", 584 }, { "zero", 556 }, { "eth", 611 }, { "Ograve", 778 }, { "uacute", 611 }, { "braceleft", 389 }, { "Thorn", 667 }, { "zcaron", 500 }, { "ccedilla", 556 }, { "Ocircumflex", 778 }, { "Oacute", 778 }, { "ogonek", 333 }, { "ograve", 611 }, { "thorn", 611 }, { "degree", 400 }, { "registered", 737 }, { "Aring", 722 }, { "percent", 889 }, { "six", 556 }, { "paragraph", 556 }, { "two", 556 }, { "Igrave", 278 }, { "ocircumflex", 611 }, { "oacute", 611 }, { "asciicircum", 584 }, { "aring", 556 }, { "grave", 333 }, { "bracketright", 333 }, { "Iacute", 278 }, { "ampersand", 722 }, { "igrave", 278 }, { "plus", 584 }, { "quotesinglbase", 278 }, { "Yacute", 667 }, { "threesuperior", 333 }, { "acute", 333 }, { "section", 556 }, { "dieresis", 333 }, { "iacute", 278 }, { "quotedblbase", 500 }, { "florin", 556 }, { "yacute", 556 }, { "fi", 611 }, { "fl", 611 }, { "Acircumflex", 722 }, { "Icircumflex", 278 }, { "guillemotleft", 556 }, { "germandbls", 611 }, { "seven", 556 }, { "ordmasculine", 365 }, { "dotlessi", 278 }, { "sterling", 556 }, { "acircumflex", 556 }, { "icircumflex", 278 }, { "braceright", 389 }, { "quotedblright", 500 }, { "cent", 556 }, { "currency", 556 }, { "logicalnot", 584 }, { "Atilde", 722 }, { "breve", 333 }, { "bar", 280 }, { "fraction", 167 }, { "less", 584 }, { "guilsinglleft", 333 }, { "exclam", 333 }, { "period", 278 }, { "greater", 584 }, { "atilde", 556 }, { "brokenbar", 280 }, { "quoteleft", 278 }, { "onesuperior", 333 } }; static const StdFontWidth helveticaBoldObliqueWidthsTab[] = { { "Ntilde", 722 }, { "comma", 278 }, { "cedilla", 333 }, { "plusminus", 584 }, { "circumflex", 333 }, { "dotaccent", 333 }, { "asciitilde", 584 }, { "colon", 333 }, { "onehalf", 834 }, { "dollar", 556 }, { "ntilde", 611 }, { "minus", 584 }, { "yen", 556 }, { "space", 278 }, { "questiondown", 611 }, { "emdash", 1000 }, { "Agrave", 722 }, { "three", 556 }, { "numbersign", 556 }, { "A", 722 }, { "B", 722 }, { "C", 722 }, { "D", 722 }, { "E", 667 }, { "onequarter", 834 }, { "F", 611 }, { "G", 778 }, { "H", 722 }, { "I", 278 }, { "J", 556 }, { "K", 722 }, { "backslash", 278 }, { "L", 611 }, { "periodcentered", 278 }, { "M", 833 }, { "N", 722 }, { "O", 778 }, { "P", 667 }, { "Q", 778 }, { "R", 722 }, { "Aacute", 722 }, { "caron", 333 }, { "S", 667 }, { "T", 611 }, { "U", 722 }, { "agrave", 556 }, { "V", 667 }, { "W", 944 }, { "X", 667 }, { "question", 611 }, { "equal", 584 }, { "Y", 667 }, { "Z", 611 }, { "four", 556 }, { "a", 556 }, { "b", 611 }, { "c", 556 }, { "d", 611 }, { "e", 556 }, { "f", 333 }, { "g", 611 }, { "bullet", 350 }, { "h", 611 }, { "i", 278 }, { "Oslash", 778 }, { "dagger", 556 }, { "j", 278 }, { "k", 556 }, { "l", 278 }, { "m", 889 }, { "n", 611 }, { "o", 611 }, { "ordfeminine", 370 }, { "ring", 333 }, { "p", 611 }, { "q", 611 }, { "r", 389 }, { "twosuperior", 333 }, { "aacute", 556 }, { "s", 556 }, { "OE", 1000 }, { "t", 333 }, { "divide", 584 }, { "u", 611 }, { "v", 556 }, { "w", 778 }, { "x", 556 }, { "y", 556 }, { "z", 500 }, { "hungarumlaut", 333 }, { "quotedbl", 474 }, { "mu", 611 }, { "Scaron", 667 }, { "Lslash", 611 }, { "semicolon", 333 }, { "oslash", 611 }, { "parenright", 333 }, { "Ecircumflex", 667 }, { "trademark", 1000 }, { "daggerdbl", 556 }, { "macron", 333 }, { "Otilde", 778 }, { "ellipsis", 1000 }, { "scaron", 556 }, { "AE", 1000 }, { "Ucircumflex", 722 }, { "lslash", 278 }, { "quotedblleft", 500 }, { "guilsinglright", 333 }, { "hyphen", 333 }, { "quotesingle", 238 }, { "eight", 556 }, { "exclamdown", 333 }, { "endash", 556 }, { "oe", 944 }, { "ecircumflex", 556 }, { "copyright", 737 }, { "Adieresis", 722 }, { "Egrave", 667 }, { "slash", 278 }, { "Edieresis", 667 }, { "otilde", 611 }, { "Idieresis", 278 }, { "parenleft", 333 }, { "one", 556 }, { "ucircumflex", 611 }, { "Odieresis", 778 }, { "bracketleft", 333 }, { "Ugrave", 722 }, { "quoteright", 278 }, { "Udieresis", 722 }, { "perthousand", 1000 }, { "Ydieresis", 667 }, { "Eacute", 667 }, { "adieresis", 556 }, { "egrave", 556 }, { "edieresis", 556 }, { "idieresis", 278 }, { "Eth", 722 }, { "ae", 889 }, { "asterisk", 389 }, { "odieresis", 611 }, { "Uacute", 722 }, { "ugrave", 611 }, { "nine", 556 }, { "five", 556 }, { "udieresis", 611 }, { "Zcaron", 611 }, { "threequarters", 834 }, { "guillemotright", 556 }, { "ydieresis", 556 }, { "Ccedilla", 722 }, { "tilde", 333 }, { "at", 975 }, { "eacute", 556 }, { "underscore", 556 }, { "multiply", 584 }, { "zero", 556 }, { "eth", 611 }, { "Ograve", 778 }, { "uacute", 611 }, { "braceleft", 389 }, { "Thorn", 667 }, { "zcaron", 500 }, { "ccedilla", 556 }, { "Ocircumflex", 778 }, { "Oacute", 778 }, { "ogonek", 333 }, { "ograve", 611 }, { "thorn", 611 }, { "degree", 400 }, { "registered", 737 }, { "Aring", 722 }, { "percent", 889 }, { "six", 556 }, { "paragraph", 556 }, { "two", 556 }, { "Igrave", 278 }, { "ocircumflex", 611 }, { "oacute", 611 }, { "asciicircum", 584 }, { "aring", 556 }, { "grave", 333 }, { "bracketright", 333 }, { "Iacute", 278 }, { "ampersand", 722 }, { "igrave", 278 }, { "plus", 584 }, { "quotesinglbase", 278 }, { "Yacute", 667 }, { "threesuperior", 333 }, { "acute", 333 }, { "section", 556 }, { "dieresis", 333 }, { "iacute", 278 }, { "quotedblbase", 500 }, { "florin", 556 }, { "yacute", 556 }, { "fi", 611 }, { "fl", 611 }, { "Acircumflex", 722 }, { "Icircumflex", 278 }, { "guillemotleft", 556 }, { "germandbls", 611 }, { "seven", 556 }, { "ordmasculine", 365 }, { "dotlessi", 278 }, { "sterling", 556 }, { "acircumflex", 556 }, { "icircumflex", 278 }, { "braceright", 389 }, { "quotedblright", 500 }, { "cent", 556 }, { "currency", 556 }, { "logicalnot", 584 }, { "Atilde", 722 }, { "breve", 333 }, { "bar", 280 }, { "fraction", 167 }, { "less", 584 }, { "guilsinglleft", 333 }, { "exclam", 333 }, { "period", 278 }, { "greater", 584 }, { "atilde", 556 }, { "brokenbar", 280 }, { "quoteleft", 278 }, { "onesuperior", 333 } }; static const StdFontWidth helveticaObliqueWidthsTab[] = { { "Ntilde", 722 }, { "comma", 278 }, { "cedilla", 333 }, { "plusminus", 584 }, { "circumflex", 333 }, { "dotaccent", 333 }, { "asciitilde", 584 }, { "colon", 278 }, { "onehalf", 834 }, { "dollar", 556 }, { "ntilde", 556 }, { "minus", 584 }, { "yen", 556 }, { "space", 278 }, { "questiondown", 611 }, { "emdash", 1000 }, { "Agrave", 667 }, { "three", 556 }, { "numbersign", 556 }, { "A", 667 }, { "B", 667 }, { "C", 722 }, { "D", 722 }, { "E", 667 }, { "onequarter", 834 }, { "F", 611 }, { "G", 778 }, { "H", 722 }, { "I", 278 }, { "J", 500 }, { "K", 667 }, { "backslash", 278 }, { "L", 556 }, { "periodcentered", 278 }, { "M", 833 }, { "N", 722 }, { "O", 778 }, { "P", 667 }, { "Q", 778 }, { "R", 722 }, { "Aacute", 667 }, { "caron", 333 }, { "S", 667 }, { "T", 611 }, { "U", 722 }, { "agrave", 556 }, { "V", 667 }, { "W", 944 }, { "X", 667 }, { "question", 556 }, { "equal", 584 }, { "Y", 667 }, { "Z", 611 }, { "four", 556 }, { "a", 556 }, { "b", 556 }, { "c", 500 }, { "d", 556 }, { "e", 556 }, { "f", 278 }, { "g", 556 }, { "bullet", 350 }, { "h", 556 }, { "i", 222 }, { "Oslash", 778 }, { "dagger", 556 }, { "j", 222 }, { "k", 500 }, { "l", 222 }, { "m", 833 }, { "n", 556 }, { "o", 556 }, { "ordfeminine", 370 }, { "ring", 333 }, { "p", 556 }, { "q", 556 }, { "r", 333 }, { "twosuperior", 333 }, { "aacute", 556 }, { "s", 500 }, { "OE", 1000 }, { "t", 278 }, { "divide", 584 }, { "u", 556 }, { "v", 500 }, { "w", 722 }, { "x", 500 }, { "y", 500 }, { "z", 500 }, { "hungarumlaut", 333 }, { "quotedbl", 355 }, { "mu", 556 }, { "Scaron", 667 }, { "Lslash", 556 }, { "semicolon", 278 }, { "oslash", 611 }, { "parenright", 333 }, { "Ecircumflex", 667 }, { "trademark", 1000 }, { "daggerdbl", 556 }, { "macron", 333 }, { "Otilde", 778 }, { "ellipsis", 1000 }, { "scaron", 500 }, { "AE", 1000 }, { "Ucircumflex", 722 }, { "lslash", 222 }, { "quotedblleft", 333 }, { "guilsinglright", 333 }, { "hyphen", 333 }, { "quotesingle", 191 }, { "eight", 556 }, { "exclamdown", 333 }, { "endash", 556 }, { "oe", 944 }, { "ecircumflex", 556 }, { "copyright", 737 }, { "Adieresis", 667 }, { "Egrave", 667 }, { "slash", 278 }, { "Edieresis", 667 }, { "otilde", 556 }, { "Idieresis", 278 }, { "parenleft", 333 }, { "one", 556 }, { "ucircumflex", 556 }, { "Odieresis", 778 }, { "bracketleft", 278 }, { "Ugrave", 722 }, { "quoteright", 222 }, { "Udieresis", 722 }, { "perthousand", 1000 }, { "Ydieresis", 667 }, { "Eacute", 667 }, { "adieresis", 556 }, { "egrave", 556 }, { "edieresis", 556 }, { "idieresis", 278 }, { "Eth", 722 }, { "ae", 889 }, { "asterisk", 389 }, { "odieresis", 556 }, { "Uacute", 722 }, { "ugrave", 556 }, { "nine", 556 }, { "five", 556 }, { "udieresis", 556 }, { "Zcaron", 611 }, { "threequarters", 834 }, { "guillemotright", 556 }, { "ydieresis", 500 }, { "Ccedilla", 722 }, { "tilde", 333 }, { "at", 1015 }, { "eacute", 556 }, { "underscore", 556 }, { "multiply", 584 }, { "zero", 556 }, { "eth", 556 }, { "Ograve", 778 }, { "uacute", 556 }, { "braceleft", 334 }, { "Thorn", 667 }, { "zcaron", 500 }, { "ccedilla", 500 }, { "Ocircumflex", 778 }, { "Oacute", 778 }, { "ogonek", 333 }, { "ograve", 556 }, { "thorn", 556 }, { "degree", 400 }, { "registered", 737 }, { "Aring", 667 }, { "percent", 889 }, { "six", 556 }, { "paragraph", 537 }, { "two", 556 }, { "Igrave", 278 }, { "ocircumflex", 556 }, { "oacute", 556 }, { "asciicircum", 469 }, { "aring", 556 }, { "grave", 333 }, { "bracketright", 278 }, { "Iacute", 278 }, { "ampersand", 667 }, { "igrave", 278 }, { "plus", 584 }, { "quotesinglbase", 222 }, { "Yacute", 667 }, { "threesuperior", 333 }, { "acute", 333 }, { "section", 556 }, { "dieresis", 333 }, { "iacute", 278 }, { "quotedblbase", 333 }, { "florin", 556 }, { "yacute", 500 }, { "fi", 500 }, { "fl", 500 }, { "Acircumflex", 667 }, { "Icircumflex", 278 }, { "guillemotleft", 556 }, { "germandbls", 611 }, { "seven", 556 }, { "ordmasculine", 365 }, { "dotlessi", 278 }, { "sterling", 556 }, { "acircumflex", 556 }, { "icircumflex", 278 }, { "braceright", 334 }, { "quotedblright", 333 }, { "cent", 556 }, { "currency", 556 }, { "logicalnot", 584 }, { "Atilde", 667 }, { "breve", 333 }, { "bar", 260 }, { "fraction", 167 }, { "less", 584 }, { "guilsinglleft", 333 }, { "exclam", 278 }, { "period", 278 }, { "greater", 584 }, { "atilde", 556 }, { "brokenbar", 260 }, { "quoteleft", 222 }, { "onesuperior", 333 } }; static const StdFontWidth symbolWidthsTab[] = { { "bracketleftex", 384 }, { "alpha", 631 }, { "union", 768 }, { "infinity", 713 }, { "comma", 250 }, { "copyrightsans", 790 }, { "plusminus", 549 }, { "arrowup", 603 }, { "apple", 790 }, { "parenleftbt", 384 }, { "notelement", 713 }, { "colon", 278 }, { "beta", 549 }, { "braceleftbt", 494 }, { "Lambda", 686 }, { "Phi", 763 }, { "minus", 549 }, { "space", 250 }, { "Sigma", 592 }, { "approxequal", 549 }, { "minute", 247 }, { "circleplus", 768 }, { "Omicron", 722 }, { "three", 500 }, { "numbersign", 500 }, { "lambda", 549 }, { "phi", 521 }, { "aleph", 823 }, { "Tau", 611 }, { "spade", 753 }, { "logicaland", 603 }, { "sigma", 603 }, { "propersuperset", 713 }, { "omicron", 549 }, { "question", 444 }, { "equal", 549 }, { "Epsilon", 611 }, { "emptyset", 823 }, { "diamond", 753 }, { "four", 500 }, { "Mu", 889 }, { "parenlefttp", 384 }, { "club", 753 }, { "bullet", 460 }, { "Omega", 768 }, { "tau", 439 }, { "Upsilon", 690 }, { "bracelefttp", 494 }, { "heart", 753 }, { "divide", 549 }, { "epsilon", 439 }, { "logicalor", 603 }, { "parenleftex", 384 }, { "greaterequal", 549 }, { "mu", 576 }, { "Nu", 722 }, { "therefore", 863 }, { "notsubset", 713 }, { "omega", 686 }, { "semicolon", 278 }, { "element", 713 }, { "upsilon", 576 }, { "existential", 549 }, { "integralbt", 686 }, { "lessequal", 549 }, { "phi1", 603 }, { "lozenge", 494 }, { "trademarkserif", 890 }, { "parenright", 333 }, { "reflexsuperset", 713 }, { "sigma1", 439 }, { "nu", 521 }, { "Gamma", 603 }, { "angleright", 329 }, { "ellipsis", 1000 }, { "Rho", 556 }, { "parenrightbt", 384 }, { "radicalex", 500 }, { "eight", 500 }, { "angleleft", 329 }, { "arrowdbldown", 603 }, { "congruent", 549 }, { "Theta", 741 }, { "intersection", 768 }, { "Pi", 768 }, { "slash", 278 }, { "registerserif", 790 }, { "parenleft", 333 }, { "one", 500 }, { "gamma", 411 }, { "bracketleft", 333 }, { "rho", 549 }, { "circlemultiply", 768 }, { "Chi", 722 }, { "theta", 521 }, { "pi", 549 }, { "integraltp", 686 }, { "Eta", 722 }, { "product", 823 }, { "nine", 500 }, { "five", 500 }, { "propersubset", 713 }, { "bracketrightbt", 384 }, { "trademarksans", 786 }, { "dotmath", 250 }, { "integralex", 686 }, { "chi", 549 }, { "parenrighttp", 384 }, { "eta", 603 }, { "underscore", 500 }, { "multiply", 549 }, { "zero", 500 }, { "partialdiff", 494 }, { "angle", 768 }, { "arrowdblleft", 987 }, { "braceleft", 480 }, { "parenrightex", 384 }, { "Rfraktur", 795 }, { "Zeta", 611 }, { "braceex", 494 }, { "arrowdblup", 603 }, { "arrowdown", 603 }, { "Ifraktur", 686 }, { "degree", 400 }, { "Iota", 333 }, { "perpendicular", 658 }, { "radical", 549 }, { "asteriskmath", 500 }, { "percent", 833 }, { "zeta", 494 }, { "six", 500 }, { "two", 500 }, { "weierstrass", 987 }, { "summation", 713 }, { "bracketrighttp", 384 }, { "carriagereturn", 658 }, { "suchthat", 439 }, { "arrowvertex", 603 }, { "Delta", 612 }, { "iota", 329 }, { "arrowhorizex", 1000 }, { "bracketrightex", 384 }, { "bracketright", 333 }, { "ampersand", 778 }, { "plus", 549 }, { "proportional", 713 }, { "delta", 494 }, { "copyrightserif", 790 }, { "bracerightmid", 494 }, { "arrowleft", 987 }, { "second", 411 }, { "arrowdblboth", 1042 }, { "florin", 500 }, { "Psi", 795 }, { "bracerightbt", 494 }, { "bracketleftbt", 384 }, { "seven", 500 }, { "braceleftmid", 494 }, { "notequal", 549 }, { "psi", 686 }, { "equivalence", 549 }, { "universal", 713 }, { "arrowdblright", 987 }, { "braceright", 480 }, { "reflexsubset", 713 }, { "Xi", 645 }, { "theta1", 631 }, { "logicalnot", 713 }, { "Kappa", 722 }, { "similar", 549 }, { "bar", 200 }, { "fraction", 167 }, { "less", 549 }, { "registersans", 790 }, { "omega1", 713 }, { "exclam", 333 }, { "Upsilon1", 620 }, { "bracerighttp", 494 }, { "xi", 493 }, { "period", 250 }, { "Alpha", 722 }, { "arrowright", 987 }, { "greater", 549 }, { "bracketlefttp", 384 }, { "kappa", 549 }, { "gradient", 713 }, { "integral", 274 }, { "arrowboth", 1042 }, { "Beta", 667 } }; static const StdFontWidth timesBoldWidthsTab[] = { { "Ntilde", 722 }, { "comma", 250 }, { "cedilla", 333 }, { "plusminus", 570 }, { "circumflex", 333 }, { "dotaccent", 333 }, { "asciitilde", 520 }, { "colon", 333 }, { "onehalf", 750 }, { "dollar", 500 }, { "ntilde", 556 }, { "minus", 570 }, { "yen", 500 }, { "space", 250 }, { "questiondown", 500 }, { "emdash", 1000 }, { "Agrave", 722 }, { "three", 500 }, { "numbersign", 500 }, { "A", 722 }, { "B", 667 }, { "C", 722 }, { "D", 722 }, { "E", 667 }, { "onequarter", 750 }, { "F", 611 }, { "G", 778 }, { "H", 778 }, { "I", 389 }, { "J", 500 }, { "K", 778 }, { "backslash", 278 }, { "L", 667 }, { "periodcentered", 250 }, { "M", 944 }, { "N", 722 }, { "O", 778 }, { "P", 611 }, { "Q", 778 }, { "R", 722 }, { "Aacute", 722 }, { "caron", 333 }, { "S", 556 }, { "T", 667 }, { "U", 722 }, { "agrave", 500 }, { "V", 722 }, { "W", 1000 }, { "X", 722 }, { "question", 500 }, { "equal", 570 }, { "Y", 722 }, { "Z", 667 }, { "four", 500 }, { "a", 500 }, { "b", 556 }, { "c", 444 }, { "d", 556 }, { "e", 444 }, { "f", 333 }, { "g", 500 }, { "bullet", 350 }, { "h", 556 }, { "i", 278 }, { "Oslash", 778 }, { "dagger", 500 }, { "j", 333 }, { "k", 556 }, { "l", 278 }, { "m", 833 }, { "n", 556 }, { "o", 500 }, { "ordfeminine", 300 }, { "ring", 333 }, { "p", 556 }, { "q", 556 }, { "r", 444 }, { "twosuperior", 300 }, { "aacute", 500 }, { "s", 389 }, { "OE", 1000 }, { "t", 333 }, { "divide", 570 }, { "u", 556 }, { "v", 500 }, { "w", 722 }, { "x", 500 }, { "y", 500 }, { "z", 444 }, { "hungarumlaut", 333 }, { "quotedbl", 555 }, { "mu", 556 }, { "Scaron", 556 }, { "Lslash", 667 }, { "semicolon", 333 }, { "oslash", 500 }, { "parenright", 333 }, { "Ecircumflex", 667 }, { "trademark", 1000 }, { "daggerdbl", 500 }, { "macron", 333 }, { "Otilde", 778 }, { "ellipsis", 1000 }, { "scaron", 389 }, { "AE", 1000 }, { "Ucircumflex", 722 }, { "lslash", 278 }, { "quotedblleft", 500 }, { "guilsinglright", 333 }, { "hyphen", 333 }, { "quotesingle", 278 }, { "eight", 500 }, { "exclamdown", 333 }, { "endash", 500 }, { "oe", 722 }, { "ecircumflex", 444 }, { "copyright", 747 }, { "Adieresis", 722 }, { "Egrave", 667 }, { "slash", 278 }, { "Edieresis", 667 }, { "otilde", 500 }, { "Idieresis", 389 }, { "parenleft", 333 }, { "one", 500 }, { "ucircumflex", 556 }, { "Odieresis", 778 }, { "bracketleft", 333 }, { "Ugrave", 722 }, { "quoteright", 333 }, { "Udieresis", 722 }, { "perthousand", 1000 }, { "Ydieresis", 722 }, { "Eacute", 667 }, { "adieresis", 500 }, { "egrave", 444 }, { "edieresis", 444 }, { "idieresis", 278 }, { "Eth", 722 }, { "ae", 722 }, { "asterisk", 500 }, { "odieresis", 500 }, { "Uacute", 722 }, { "ugrave", 556 }, { "nine", 500 }, { "five", 500 }, { "udieresis", 556 }, { "Zcaron", 667 }, { "threequarters", 750 }, { "guillemotright", 500 }, { "ydieresis", 500 }, { "Ccedilla", 722 }, { "tilde", 333 }, { "at", 930 }, { "eacute", 444 }, { "underscore", 500 }, { "multiply", 570 }, { "zero", 500 }, { "eth", 500 }, { "Ograve", 778 }, { "uacute", 556 }, { "braceleft", 394 }, { "Thorn", 611 }, { "zcaron", 444 }, { "ccedilla", 444 }, { "Ocircumflex", 778 }, { "Oacute", 778 }, { "ogonek", 333 }, { "ograve", 500 }, { "thorn", 556 }, { "degree", 400 }, { "registered", 747 }, { "Aring", 722 }, { "percent", 1000 }, { "six", 500 }, { "paragraph", 540 }, { "two", 500 }, { "Igrave", 389 }, { "ocircumflex", 500 }, { "oacute", 500 }, { "asciicircum", 581 }, { "aring", 500 }, { "grave", 333 }, { "bracketright", 333 }, { "Iacute", 389 }, { "ampersand", 833 }, { "igrave", 278 }, { "plus", 570 }, { "quotesinglbase", 333 }, { "Yacute", 722 }, { "threesuperior", 300 }, { "acute", 333 }, { "section", 500 }, { "dieresis", 333 }, { "iacute", 278 }, { "quotedblbase", 500 }, { "florin", 500 }, { "yacute", 500 }, { "fi", 556 }, { "fl", 556 }, { "Acircumflex", 722 }, { "Icircumflex", 389 }, { "guillemotleft", 500 }, { "germandbls", 556 }, { "seven", 500 }, { "ordmasculine", 330 }, { "dotlessi", 278 }, { "sterling", 500 }, { "acircumflex", 500 }, { "icircumflex", 278 }, { "braceright", 394 }, { "quotedblright", 500 }, { "cent", 500 }, { "currency", 500 }, { "logicalnot", 570 }, { "Atilde", 722 }, { "breve", 333 }, { "bar", 220 }, { "fraction", 167 }, { "less", 570 }, { "guilsinglleft", 333 }, { "exclam", 333 }, { "period", 250 }, { "greater", 570 }, { "atilde", 500 }, { "brokenbar", 220 }, { "quoteleft", 333 }, { "onesuperior", 300 } }; static const StdFontWidth timesBoldItalicWidthsTab[] = { { "Ntilde", 722 }, { "comma", 250 }, { "cedilla", 333 }, { "plusminus", 570 }, { "circumflex", 333 }, { "dotaccent", 333 }, { "asciitilde", 570 }, { "colon", 333 }, { "onehalf", 750 }, { "dollar", 500 }, { "ntilde", 556 }, { "minus", 606 }, { "yen", 500 }, { "space", 250 }, { "questiondown", 500 }, { "emdash", 1000 }, { "Agrave", 667 }, { "three", 500 }, { "numbersign", 500 }, { "A", 667 }, { "B", 667 }, { "C", 667 }, { "D", 722 }, { "E", 667 }, { "onequarter", 750 }, { "F", 667 }, { "G", 722 }, { "H", 778 }, { "I", 389 }, { "J", 500 }, { "K", 667 }, { "backslash", 278 }, { "L", 611 }, { "periodcentered", 250 }, { "M", 889 }, { "N", 722 }, { "O", 722 }, { "P", 611 }, { "Q", 722 }, { "R", 667 }, { "Aacute", 667 }, { "caron", 333 }, { "S", 556 }, { "T", 611 }, { "U", 722 }, { "agrave", 500 }, { "V", 667 }, { "W", 889 }, { "X", 667 }, { "question", 500 }, { "equal", 570 }, { "Y", 611 }, { "Z", 611 }, { "four", 500 }, { "a", 500 }, { "b", 500 }, { "c", 444 }, { "d", 500 }, { "e", 444 }, { "f", 333 }, { "g", 500 }, { "bullet", 350 }, { "h", 556 }, { "i", 278 }, { "Oslash", 722 }, { "dagger", 500 }, { "j", 278 }, { "k", 500 }, { "l", 278 }, { "m", 778 }, { "n", 556 }, { "o", 500 }, { "ordfeminine", 266 }, { "ring", 333 }, { "p", 500 }, { "q", 500 }, { "r", 389 }, { "twosuperior", 300 }, { "aacute", 500 }, { "s", 389 }, { "OE", 944 }, { "t", 278 }, { "divide", 570 }, { "u", 556 }, { "v", 444 }, { "w", 667 }, { "x", 500 }, { "y", 444 }, { "z", 389 }, { "hungarumlaut", 333 }, { "quotedbl", 555 }, { "mu", 576 }, { "Scaron", 556 }, { "Lslash", 611 }, { "semicolon", 333 }, { "oslash", 500 }, { "parenright", 333 }, { "Ecircumflex", 667 }, { "trademark", 1000 }, { "daggerdbl", 500 }, { "macron", 333 }, { "Otilde", 722 }, { "ellipsis", 1000 }, { "scaron", 389 }, { "AE", 944 }, { "Ucircumflex", 722 }, { "lslash", 278 }, { "quotedblleft", 500 }, { "guilsinglright", 333 }, { "hyphen", 333 }, { "quotesingle", 278 }, { "eight", 500 }, { "exclamdown", 389 }, { "endash", 500 }, { "oe", 722 }, { "ecircumflex", 444 }, { "copyright", 747 }, { "Adieresis", 667 }, { "Egrave", 667 }, { "slash", 278 }, { "Edieresis", 667 }, { "otilde", 500 }, { "Idieresis", 389 }, { "parenleft", 333 }, { "one", 500 }, { "ucircumflex", 556 }, { "Odieresis", 722 }, { "bracketleft", 333 }, { "Ugrave", 722 }, { "quoteright", 333 }, { "Udieresis", 722 }, { "perthousand", 1000 }, { "Ydieresis", 611 }, { "Eacute", 667 }, { "adieresis", 500 }, { "egrave", 444 }, { "edieresis", 444 }, { "idieresis", 278 }, { "Eth", 722 }, { "ae", 722 }, { "asterisk", 500 }, { "odieresis", 500 }, { "Uacute", 722 }, { "ugrave", 556 }, { "nine", 500 }, { "five", 500 }, { "udieresis", 556 }, { "Zcaron", 611 }, { "threequarters", 750 }, { "guillemotright", 500 }, { "ydieresis", 444 }, { "Ccedilla", 667 }, { "tilde", 333 }, { "at", 832 }, { "eacute", 444 }, { "underscore", 500 }, { "multiply", 570 }, { "zero", 500 }, { "eth", 500 }, { "Ograve", 722 }, { "uacute", 556 }, { "braceleft", 348 }, { "Thorn", 611 }, { "zcaron", 389 }, { "ccedilla", 444 }, { "Ocircumflex", 722 }, { "Oacute", 722 }, { "ogonek", 333 }, { "ograve", 500 }, { "thorn", 500 }, { "degree", 400 }, { "registered", 747 }, { "Aring", 667 }, { "percent", 833 }, { "six", 500 }, { "paragraph", 500 }, { "two", 500 }, { "Igrave", 389 }, { "ocircumflex", 500 }, { "oacute", 500 }, { "asciicircum", 570 }, { "aring", 500 }, { "grave", 333 }, { "bracketright", 333 }, { "Iacute", 389 }, { "ampersand", 778 }, { "igrave", 278 }, { "plus", 570 }, { "quotesinglbase", 333 }, { "Yacute", 611 }, { "threesuperior", 300 }, { "acute", 333 }, { "section", 500 }, { "dieresis", 333 }, { "iacute", 278 }, { "quotedblbase", 500 }, { "florin", 500 }, { "yacute", 444 }, { "fi", 556 }, { "fl", 556 }, { "Acircumflex", 667 }, { "Icircumflex", 389 }, { "guillemotleft", 500 }, { "germandbls", 500 }, { "seven", 500 }, { "ordmasculine", 300 }, { "dotlessi", 278 }, { "sterling", 500 }, { "acircumflex", 500 }, { "icircumflex", 278 }, { "braceright", 348 }, { "quotedblright", 500 }, { "cent", 500 }, { "currency", 500 }, { "logicalnot", 606 }, { "Atilde", 667 }, { "breve", 333 }, { "bar", 220 }, { "fraction", 167 }, { "less", 570 }, { "guilsinglleft", 333 }, { "exclam", 389 }, { "period", 250 }, { "greater", 570 }, { "atilde", 500 }, { "brokenbar", 220 }, { "quoteleft", 333 }, { "onesuperior", 300 } }; static const StdFontWidth timesItalicWidthsTab[] = { { "Ntilde", 667 }, { "comma", 250 }, { "cedilla", 333 }, { "plusminus", 675 }, { "circumflex", 333 }, { "dotaccent", 333 }, { "asciitilde", 541 }, { "colon", 333 }, { "onehalf", 750 }, { "dollar", 500 }, { "ntilde", 500 }, { "minus", 675 }, { "yen", 500 }, { "space", 250 }, { "questiondown", 500 }, { "emdash", 889 }, { "Agrave", 611 }, { "three", 500 }, { "numbersign", 500 }, { "A", 611 }, { "B", 611 }, { "C", 667 }, { "D", 722 }, { "E", 611 }, { "onequarter", 750 }, { "F", 611 }, { "G", 722 }, { "H", 722 }, { "I", 333 }, { "J", 444 }, { "K", 667 }, { "backslash", 278 }, { "L", 556 }, { "periodcentered", 250 }, { "M", 833 }, { "N", 667 }, { "O", 722 }, { "P", 611 }, { "Q", 722 }, { "R", 611 }, { "Aacute", 611 }, { "caron", 333 }, { "S", 500 }, { "T", 556 }, { "U", 722 }, { "agrave", 500 }, { "V", 611 }, { "W", 833 }, { "X", 611 }, { "question", 500 }, { "equal", 675 }, { "Y", 556 }, { "Z", 556 }, { "four", 500 }, { "a", 500 }, { "b", 500 }, { "c", 444 }, { "d", 500 }, { "e", 444 }, { "f", 278 }, { "g", 500 }, { "bullet", 350 }, { "h", 500 }, { "i", 278 }, { "Oslash", 722 }, { "dagger", 500 }, { "j", 278 }, { "k", 444 }, { "l", 278 }, { "m", 722 }, { "n", 500 }, { "o", 500 }, { "ordfeminine", 276 }, { "ring", 333 }, { "p", 500 }, { "q", 500 }, { "r", 389 }, { "twosuperior", 300 }, { "aacute", 500 }, { "s", 389 }, { "OE", 944 }, { "t", 278 }, { "divide", 675 }, { "u", 500 }, { "v", 444 }, { "w", 667 }, { "x", 444 }, { "y", 444 }, { "z", 389 }, { "hungarumlaut", 333 }, { "quotedbl", 420 }, { "mu", 500 }, { "Scaron", 500 }, { "Lslash", 556 }, { "semicolon", 333 }, { "oslash", 500 }, { "parenright", 333 }, { "Ecircumflex", 611 }, { "trademark", 980 }, { "daggerdbl", 500 }, { "macron", 333 }, { "Otilde", 722 }, { "ellipsis", 889 }, { "scaron", 389 }, { "AE", 889 }, { "Ucircumflex", 722 }, { "lslash", 278 }, { "quotedblleft", 556 }, { "guilsinglright", 333 }, { "hyphen", 333 }, { "quotesingle", 214 }, { "eight", 500 }, { "exclamdown", 389 }, { "endash", 500 }, { "oe", 667 }, { "ecircumflex", 444 }, { "copyright", 760 }, { "Adieresis", 611 }, { "Egrave", 611 }, { "slash", 278 }, { "Edieresis", 611 }, { "otilde", 500 }, { "Idieresis", 333 }, { "parenleft", 333 }, { "one", 500 }, { "ucircumflex", 500 }, { "Odieresis", 722 }, { "bracketleft", 389 }, { "Ugrave", 722 }, { "quoteright", 333 }, { "Udieresis", 722 }, { "perthousand", 1000 }, { "Ydieresis", 556 }, { "Eacute", 611 }, { "adieresis", 500 }, { "egrave", 444 }, { "edieresis", 444 }, { "idieresis", 278 }, { "Eth", 722 }, { "ae", 667 }, { "asterisk", 500 }, { "odieresis", 500 }, { "Uacute", 722 }, { "ugrave", 500 }, { "nine", 500 }, { "five", 500 }, { "udieresis", 500 }, { "Zcaron", 556 }, { "threequarters", 750 }, { "guillemotright", 500 }, { "ydieresis", 444 }, { "Ccedilla", 667 }, { "tilde", 333 }, { "at", 920 }, { "eacute", 444 }, { "underscore", 500 }, { "multiply", 675 }, { "zero", 500 }, { "eth", 500 }, { "Ograve", 722 }, { "uacute", 500 }, { "braceleft", 400 }, { "Thorn", 611 }, { "zcaron", 389 }, { "ccedilla", 444 }, { "Ocircumflex", 722 }, { "Oacute", 722 }, { "ogonek", 333 }, { "ograve", 500 }, { "thorn", 500 }, { "degree", 400 }, { "registered", 760 }, { "Aring", 611 }, { "percent", 833 }, { "six", 500 }, { "paragraph", 523 }, { "two", 500 }, { "Igrave", 333 }, { "ocircumflex", 500 }, { "oacute", 500 }, { "asciicircum", 422 }, { "aring", 500 }, { "grave", 333 }, { "bracketright", 389 }, { "Iacute", 333 }, { "ampersand", 778 }, { "igrave", 278 }, { "plus", 675 }, { "quotesinglbase", 333 }, { "Yacute", 556 }, { "threesuperior", 300 }, { "acute", 333 }, { "section", 500 }, { "dieresis", 333 }, { "iacute", 278 }, { "quotedblbase", 556 }, { "florin", 500 }, { "yacute", 444 }, { "fi", 500 }, { "fl", 500 }, { "Acircumflex", 611 }, { "Icircumflex", 333 }, { "guillemotleft", 500 }, { "germandbls", 500 }, { "seven", 500 }, { "ordmasculine", 310 }, { "dotlessi", 278 }, { "sterling", 500 }, { "acircumflex", 500 }, { "icircumflex", 278 }, { "braceright", 400 }, { "quotedblright", 556 }, { "cent", 500 }, { "currency", 500 }, { "logicalnot", 675 }, { "Atilde", 611 }, { "breve", 333 }, { "bar", 275 }, { "fraction", 167 }, { "less", 675 }, { "guilsinglleft", 333 }, { "exclam", 333 }, { "period", 250 }, { "greater", 675 }, { "atilde", 500 }, { "brokenbar", 275 }, { "quoteleft", 333 }, { "onesuperior", 300 } }; static const StdFontWidth timesRomanWidthsTab[] = { { "Ntilde", 722 }, { "comma", 250 }, { "cedilla", 333 }, { "plusminus", 564 }, { "circumflex", 333 }, { "dotaccent", 333 }, { "asciitilde", 541 }, { "colon", 278 }, { "onehalf", 750 }, { "dollar", 500 }, { "ntilde", 500 }, { "minus", 564 }, { "yen", 500 }, { "space", 250 }, { "questiondown", 444 }, { "emdash", 1000 }, { "Agrave", 722 }, { "three", 500 }, { "numbersign", 500 }, { "A", 722 }, { "B", 667 }, { "C", 667 }, { "D", 722 }, { "E", 611 }, { "onequarter", 750 }, { "F", 556 }, { "G", 722 }, { "H", 722 }, { "I", 333 }, { "J", 389 }, { "K", 722 }, { "backslash", 278 }, { "L", 611 }, { "periodcentered", 250 }, { "M", 889 }, { "N", 722 }, { "O", 722 }, { "P", 556 }, { "Q", 722 }, { "R", 667 }, { "Aacute", 722 }, { "caron", 333 }, { "S", 556 }, { "T", 611 }, { "U", 722 }, { "agrave", 444 }, { "V", 722 }, { "W", 944 }, { "X", 722 }, { "question", 444 }, { "equal", 564 }, { "Y", 722 }, { "Z", 611 }, { "four", 500 }, { "a", 444 }, { "b", 500 }, { "c", 444 }, { "d", 500 }, { "e", 444 }, { "f", 333 }, { "g", 500 }, { "bullet", 350 }, { "h", 500 }, { "i", 278 }, { "Oslash", 722 }, { "dagger", 500 }, { "j", 278 }, { "k", 500 }, { "l", 278 }, { "m", 778 }, { "n", 500 }, { "o", 500 }, { "ordfeminine", 276 }, { "ring", 333 }, { "p", 500 }, { "q", 500 }, { "r", 333 }, { "twosuperior", 300 }, { "aacute", 444 }, { "s", 389 }, { "OE", 889 }, { "t", 278 }, { "divide", 564 }, { "u", 500 }, { "v", 500 }, { "w", 722 }, { "x", 500 }, { "y", 500 }, { "z", 444 }, { "hungarumlaut", 333 }, { "quotedbl", 408 }, { "mu", 500 }, { "Scaron", 556 }, { "Lslash", 611 }, { "semicolon", 278 }, { "oslash", 500 }, { "parenright", 333 }, { "Ecircumflex", 611 }, { "trademark", 980 }, { "daggerdbl", 500 }, { "macron", 333 }, { "Otilde", 722 }, { "ellipsis", 1000 }, { "scaron", 389 }, { "AE", 889 }, { "Ucircumflex", 722 }, { "lslash", 278 }, { "quotedblleft", 444 }, { "guilsinglright", 333 }, { "hyphen", 333 }, { "quotesingle", 180 }, { "eight", 500 }, { "exclamdown", 333 }, { "endash", 500 }, { "oe", 722 }, { "ecircumflex", 444 }, { "copyright", 760 }, { "Adieresis", 722 }, { "Egrave", 611 }, { "slash", 278 }, { "Edieresis", 611 }, { "otilde", 500 }, { "Idieresis", 333 }, { "parenleft", 333 }, { "one", 500 }, { "ucircumflex", 500 }, { "Odieresis", 722 }, { "bracketleft", 333 }, { "Ugrave", 722 }, { "quoteright", 333 }, { "Udieresis", 722 }, { "perthousand", 1000 }, { "Ydieresis", 722 }, { "Eacute", 611 }, { "adieresis", 444 }, { "egrave", 444 }, { "edieresis", 444 }, { "idieresis", 278 }, { "Eth", 722 }, { "ae", 667 }, { "asterisk", 500 }, { "odieresis", 500 }, { "Uacute", 722 }, { "ugrave", 500 }, { "nine", 500 }, { "five", 500 }, { "udieresis", 500 }, { "Zcaron", 611 }, { "threequarters", 750 }, { "guillemotright", 500 }, { "ydieresis", 500 }, { "Ccedilla", 667 }, { "tilde", 333 }, { "at", 921 }, { "eacute", 444 }, { "underscore", 500 }, { "multiply", 564 }, { "zero", 500 }, { "eth", 500 }, { "Ograve", 722 }, { "uacute", 500 }, { "braceleft", 480 }, { "Thorn", 556 }, { "zcaron", 444 }, { "ccedilla", 444 }, { "Ocircumflex", 722 }, { "Oacute", 722 }, { "ogonek", 333 }, { "ograve", 500 }, { "thorn", 500 }, { "degree", 400 }, { "registered", 760 }, { "Aring", 722 }, { "percent", 833 }, { "six", 500 }, { "paragraph", 453 }, { "two", 500 }, { "Igrave", 333 }, { "ocircumflex", 500 }, { "oacute", 500 }, { "asciicircum", 469 }, { "aring", 444 }, { "grave", 333 }, { "bracketright", 333 }, { "Iacute", 333 }, { "ampersand", 778 }, { "igrave", 278 }, { "plus", 564 }, { "quotesinglbase", 333 }, { "Yacute", 722 }, { "threesuperior", 300 }, { "acute", 333 }, { "section", 500 }, { "dieresis", 333 }, { "iacute", 278 }, { "quotedblbase", 444 }, { "florin", 500 }, { "yacute", 500 }, { "fi", 556 }, { "fl", 556 }, { "Acircumflex", 722 }, { "Icircumflex", 333 }, { "guillemotleft", 500 }, { "germandbls", 500 }, { "seven", 500 }, { "ordmasculine", 310 }, { "dotlessi", 278 }, { "sterling", 500 }, { "acircumflex", 444 }, { "icircumflex", 278 }, { "braceright", 480 }, { "quotedblright", 444 }, { "cent", 500 }, { "currency", 500 }, { "logicalnot", 564 }, { "Atilde", 722 }, { "breve", 333 }, { "bar", 200 }, { "fraction", 167 }, { "less", 564 }, { "guilsinglleft", 333 }, { "exclam", 333 }, { "period", 250 }, { "greater", 564 }, { "atilde", 444 }, { "brokenbar", 200 }, { "quoteleft", 333 }, { "onesuperior", 300 } }; static const StdFontWidth zapfDingbatsWidthsTab[] = { { "a81", 438 }, { "a82", 138 }, { "a83", 277 }, { "a84", 415 }, { "a85", 509 }, { "a86", 410 }, { "a87", 234 }, { "a88", 234 }, { "a89", 390 }, { "a140", 788 }, { "a141", 788 }, { "a142", 788 }, { "a143", 788 }, { "a144", 788 }, { "a145", 788 }, { "a146", 788 }, { "a147", 788 }, { "a148", 788 }, { "a149", 788 }, { "a90", 390 }, { "a91", 276 }, { "a92", 276 }, { "space", 278 }, { "a93", 317 }, { "a94", 317 }, { "a95", 334 }, { "a96", 334 }, { "a97", 392 }, { "a98", 392 }, { "a99", 668 }, { "a150", 788 }, { "a151", 788 }, { "a152", 788 }, { "a153", 788 }, { "a154", 788 }, { "a155", 788 }, { "a156", 788 }, { "a157", 788 }, { "a158", 788 }, { "a159", 788 }, { "a160", 894 }, { "a161", 838 }, { "a162", 924 }, { "a163", 1016 }, { "a164", 458 }, { "a165", 924 }, { "a166", 918 }, { "a167", 927 }, { "a168", 928 }, { "a169", 928 }, { "a170", 834 }, { "a171", 873 }, { "a172", 828 }, { "a173", 924 }, { "a174", 917 }, { "a175", 930 }, { "a176", 931 }, { "a177", 463 }, { "a178", 883 }, { "a179", 836 }, { "a180", 867 }, { "a181", 696 }, { "a182", 874 }, { "a183", 760 }, { "a184", 946 }, { "a185", 865 }, { "a186", 967 }, { "a187", 831 }, { "a188", 873 }, { "a189", 927 }, { "a1", 974 }, { "a2", 961 }, { "a3", 980 }, { "a4", 719 }, { "a5", 789 }, { "a6", 494 }, { "a7", 552 }, { "a8", 537 }, { "a9", 577 }, { "a190", 970 }, { "a191", 918 }, { "a192", 748 }, { "a193", 836 }, { "a194", 771 }, { "a195", 888 }, { "a196", 748 }, { "a197", 771 }, { "a198", 888 }, { "a199", 867 }, { "a10", 692 }, { "a11", 960 }, { "a12", 939 }, { "a13", 549 }, { "a14", 855 }, { "a15", 911 }, { "a16", 933 }, { "a17", 945 }, { "a18", 974 }, { "a19", 755 }, { "a20", 846 }, { "a21", 762 }, { "a22", 761 }, { "a23", 571 }, { "a24", 677 }, { "a25", 763 }, { "a26", 760 }, { "a27", 759 }, { "a28", 754 }, { "a29", 786 }, { "a30", 788 }, { "a31", 788 }, { "a32", 790 }, { "a33", 793 }, { "a34", 794 }, { "a35", 816 }, { "a36", 823 }, { "a37", 789 }, { "a38", 841 }, { "a39", 823 }, { "a40", 833 }, { "a41", 816 }, { "a42", 831 }, { "a43", 923 }, { "a44", 744 }, { "a45", 723 }, { "a46", 749 }, { "a47", 790 }, { "a48", 792 }, { "a49", 695 }, { "a100", 668 }, { "a101", 732 }, { "a102", 544 }, { "a103", 544 }, { "a104", 910 }, { "a105", 911 }, { "a106", 667 }, { "a107", 760 }, { "a108", 760 }, { "a109", 626 }, { "a50", 776 }, { "a51", 768 }, { "a52", 792 }, { "a53", 759 }, { "a54", 707 }, { "a55", 708 }, { "a56", 682 }, { "a57", 701 }, { "a58", 826 }, { "a59", 815 }, { "a110", 694 }, { "a111", 595 }, { "a112", 776 }, { "a117", 690 }, { "a118", 791 }, { "a119", 790 }, { "a60", 789 }, { "a61", 789 }, { "a62", 707 }, { "a63", 687 }, { "a64", 696 }, { "a65", 689 }, { "a66", 786 }, { "a67", 787 }, { "a68", 713 }, { "a69", 791 }, { "a200", 696 }, { "a201", 874 }, { "a120", 788 }, { "a121", 788 }, { "a202", 974 }, { "a122", 788 }, { "a203", 762 }, { "a123", 788 }, { "a204", 759 }, { "a205", 509 }, { "a124", 788 }, { "a206", 410 }, { "a125", 788 }, { "a126", 788 }, { "a127", 788 }, { "a128", 788 }, { "a129", 788 }, { "a70", 785 }, { "a71", 791 }, { "a72", 873 }, { "a73", 761 }, { "a74", 762 }, { "a75", 759 }, { "a76", 892 }, { "a77", 892 }, { "a78", 788 }, { "a79", 784 }, { "a130", 788 }, { "a131", 788 }, { "a132", 788 }, { "a133", 788 }, { "a134", 788 }, { "a135", 788 }, { "a136", 788 }, { "a137", 788 }, { "a138", 788 }, { "a139", 788 } }; // -------------------------------------------------------------------- static const StdFontData stdFonts[] = { { "Courier", 0, 0, 624, -207, { -40, -290, 640, 795} }, { "Courier-Bold", 0, 0, 674, -257, {-100, -350, 700, 855} }, { "Courier-BoldOblique", 0, 0, 674, -257, {-145, -350, 817, 855} }, { "Courier-Oblique", 0, 0, 624, -207, { -85, -290, 759, 795} }, { "Helvetica", helveticaWidthsTab, 228, 729, -219, {-174, -220, 1001, 944} }, { "Helvetica-Bold", helveticaBoldWidthsTab, 229, 729, -219, {-173, -221, 1003, 936} }, { "Helvetica-BoldOblique", helveticaBoldObliqueWidthsTab, 228, 729, -219, {-177, -221, 1107, 936} }, { "Helvetica-Oblique", helveticaObliqueWidthsTab, 228, 729, -219, {-178, -220, 1108, 944} }, { "Symbol", symbolWidthsTab, 189, 1010, -293, {-180, -293, 1090, 1010} }, { "Times-Bold", timesBoldWidthsTab, 228, 670, -210, {-172, -256, 1008, 965} }, { "Times-BoldItalic", timesBoldItalicWidthsTab, 228, 682, -203, {-168, -232, 1014, 894} }, { "Times-Italic", timesItalicWidthsTab, 228, 684, -206, {-176, -252, 990, 930} }, { "Times-Roman", timesRomanWidthsTab, 228, 682, -217, {-170, -223, 1024, 896} }, { "ZapfDingbats", zapfDingbatsWidthsTab, 202, 820, -143, { -1, -143, 981, 820} } }; // -------------------------------------------------------------------- bool getStdFontWidths(String fontName, const String encoding[0x100], int width[0x100]) { for (int i = 0; i < 14; ++i) { if (fontName == stdFonts[i].iName) { const StdFontWidth *wid = stdFonts[i].iWidths; int num = stdFonts[i].iNumWidths; // ipeDebug("Found %s at %d, %d glyphs", fontName.z(), i, num); if (num == 0) { // Courier fonts are monospaced for (int j = 0; j < 0x100; ++j) width[j] = 600; return true; } for (int j = 0; j < 0x100; ++j) { String glyphName = encoding[j]; if (glyphName == ".notdef") { width[j] = 0; } else { int k = 0; while (k < num && glyphName != wid[k].iName) { ++k; } if (k == num) { ipeDebug("Cannot find width for glyph '%s' in '%s'", glyphName.z(), fontName.z()); width[j] = 0; } else width[j] = wid[k].iWidth; } } return true; } } return false; } // -------------------------------------------------------------------- ipe-7.1.4/src/ipecairo/Makefile0000644000175000017500000000207012120621776016177 0ustar otfriedotfried# -------------------------------------------------------------------- # Makefile for Ipecairo # -------------------------------------------------------------------- OBJDIR = $(BUILDDIR)/obj/ipecairo include ../common.mak TARGET = $(call dll_target,ipecairo) MAKE_SYMLINKS = $(call dll_symlinks,ipecairo) SONAME = $(call soname,ipecairo) INSTALL_SYMLINKS = $(call install_symlinks,ipecairo) CPPFLAGS += -I../include $(CAIRO_CFLAGS) $(FREETYPE_CFLAGS) LIBS += -L$(buildlib) -lipe $(CAIRO_LIBS) $(FREETYPE_LIBS) CXXFLAGS += $(DLL_CFLAGS) all: $(TARGET) sources = \ ipecairopainter.cpp \ ipefonts.cpp \ ipestdfonts.cpp \ ipethumbs.cpp $(TARGET): $(objects) $(MAKE_LIBDIR) $(CXX) $(LDFLAGS) $(DLL_LDFLAGS) $(SONAME) -o $@ $^ $(LIBS) $(MAKE_SYMLINKS) clean: @-rm -f $(objects) $(TARGET) $(DEPEND) $(DEPEND): Makefile $(MAKE_DEPEND) -include $(DEPEND) install: $(TARGET) $(INSTALL_DIR) $(INSTALL_ROOT)$(IPELIBDIR) $(INSTALL_PROGRAMS) $(TARGET) $(INSTALL_ROOT)$(IPELIBDIR) $(INSTALL_SYMLINKS) # -------------------------------------------------------------------- ipe-7.1.4/src/ipecairo/ipefonts.h0000644000175000017500000000471512120621776016547 0ustar otfriedotfried// -*- C++ -*- // -------------------------------------------------------------------- // CanvasFonts maintains the Freetype fonts for the canvas // -------------------------------------------------------------------- /* This file is part of the extensible drawing editor Ipe. Copyright (C) 1993-2013 Otfried Cheong Ipe is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. As a special exception, you have permission to link Ipe with the CGAL library and distribute executables, as long as you follow the requirements of the Gnu General Public License in regard to all of the software in the executable aside from CGAL. Ipe 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 General Public License for more details. You should have received a copy of the GNU General Public License along with Ipe; if not, you can find it at "http://www.gnu.org/copyleft/gpl.html", or write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ #ifndef IPEFONTS_H #define IPEFONTS_H #include "ipebase.h" #include "ipegeo.h" #include "ipefontpool.h" #include //------------------------------------------------------------------------ struct FT_FaceRec_; namespace ipe { class Face { public: Face(int id, const Font &font); ~Face(); inline bool matches(int id) const { return id == iId; } inline Font::TType type() const { return iType; } inline int width(int ch) const { return iWidth[ch]; } inline cairo_font_face_t *cairoFont() { return iCairoFont; } int getGlyph(int ch); private: int iId; Font::TType iType; int iGlyphIndex[0x100]; int iWidth[0x100]; cairo_font_face_t *iCairoFont; }; class Fonts { public: static Fonts *New(const FontPool *fontPool); ~Fonts(); Face *getFace(int id); static cairo_font_face_t *screenFont(); static String freetypeVersion(); private: Fonts(const FontPool *fontPool); private: const FontPool *iFontPool; typedef std::list FaceSeq; FaceSeq iFaces; }; } // namespace //------------------------------------------------------------------------ #endif ipe-7.1.4/src/ipecairo/ipecairopainter.h0000644000175000017500000000633712120621776020100 0ustar otfriedotfried// -*- C++ -*- // -------------------------------------------------------------------- // ipe::CairoPainter // -------------------------------------------------------------------- /* This file is part of the extensible drawing editor Ipe. Copyright (C) 1993-2013 Otfried Cheong Ipe is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. As a special exception, you have permission to link Ipe with the CGAL library and distribute executables, as long as you follow the requirements of the Gnu General Public License in regard to all of the software in the executable aside from CGAL. Ipe 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 General Public License for more details. You should have received a copy of the GNU General Public License along with Ipe; if not, you can find it at "http://www.gnu.org/copyleft/gpl.html", or write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ #ifndef IPECAIROPAINTER_H #define IPECAIROPAINTER_H #include "ipeattributes.h" #include "ipepainter.h" #include "ipefonts.h" #include // -------------------------------------------------------------------- namespace ipe { class Cascade; class PdfObj; class CairoPainter : public Painter { public: CairoPainter(const Cascade *sheet, Fonts *fonts, cairo_t *cc, double zoom, bool pretty); virtual ~CairoPainter() { } void setDimmed(bool dim) { iDimmed = dim; } protected: virtual void doPush(); virtual void doPop(); virtual void doMoveTo(const Vector &v); virtual void doLineTo(const Vector &v); virtual void doCurveTo(const Vector &v1, const Vector &v2, const Vector &v3); virtual void doClosePath(); virtual void doDrawArc(const Arc &arc); virtual void doAddClipPath(); virtual void doDrawPath(TPathMode mode); virtual void doDrawBitmap(Bitmap bitmap); virtual void doDrawText(const Text *text); private: // void DimColor(QColor &col); void drawGlyphs(std::vector &glyphs); void execute(const Buffer &buffer); void clearArgs(); void opcm(); void opBT(); void opTf(); void opTd(); void opTJ(); void opk(bool stroke); void opg(bool stroke); void oprg(bool stroke); void opw(); void opm(); void opl(); void opq(); void opQ(); void opre(); void opsym(); private: Fonts *iFonts; cairo_t *iCairo; double iZoom; bool iPretty; bool iDimmed; bool iAfterMoveTo; // PDF operator drawing std::vector iArgs; double iTextRgb[3]; double iStrokeRgb[3]; double iFillRgb[3]; double iLineWid; Vector iMoveTo; // text state Face *iFont; // not owned Linear iFontMatrix; double iFontSize; Vector iTextLinePos; Vector iTextPos; }; } // namespace // -------------------------------------------------------------------- #endif ipe-7.1.4/src/ipecairo/ipecairopainter.cpp0000644000175000017500000004526312120621776020434 0ustar otfriedotfried// -------------------------------------------------------------------- // Painter using Cairo library // -------------------------------------------------------------------- /* This file is part of the extensible drawing editor Ipe. Copyright (C) 1993-2013 Otfried Cheong Ipe is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. As a special exception, you have permission to link Ipe with the CGAL library and distribute executables, as long as you follow the requirements of the Gnu General Public License in regard to all of the software in the executable aside from CGAL. Ipe 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 General Public License for more details. You should have received a copy of the GNU General Public License along with Ipe; if not, you can find it at "http://www.gnu.org/copyleft/gpl.html", or write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ #include "ipetext.h" #include "ipepdfparser.h" #include "ipecairopainter.h" #include "ipefonts.h" using namespace ipe; // -------------------------------------------------------------------- /*! \defgroup cairo Ipe Cairo interface \brief Drawing Ipe objects using the Cairo library. This module contains the classes needed to render Ipe objects using the Cairo and Freetype libraries. These classes are not in Ipelib, but in a separate library libipecairo. */ // -------------------------------------------------------------------- /*! \class ipe::CairoPainter \ingroup cairo \brief Ipe Painter using Cairo and Freetype as a backend. This painter draws to a Cairo surface. */ //! Construct a painter. /*! \a zoom one means 72 pixels per inch. Set \a pretty to true to avoid drawing text without Latex. */ CairoPainter::CairoPainter(const Cascade *sheet, Fonts *fonts, cairo_t *cc, double zoom, bool pretty) : Painter(sheet), iFonts(fonts), iCairo(cc), iZoom(zoom), iPretty(pretty) { iDimmed = false; iFont = 0; } void CairoPainter::doPush() { cairo_save(iCairo); } void CairoPainter::doPop() { cairo_restore(iCairo); } void CairoPainter::doMoveTo(const Vector &u) { cairo_move_to(iCairo, u.x, u.y); iAfterMoveTo = true; } void CairoPainter::doLineTo(const Vector &u) { cairo_line_to(iCairo, u.x, u.y); iAfterMoveTo = false; } void CairoPainter::doCurveTo(const Vector &u1, const Vector &u2, const Vector &u3) { cairo_curve_to(iCairo, u1.x, u1.y, u2.x, u2.y, u3.x, u3.y); iAfterMoveTo = false; } void CairoPainter::doClosePath() { cairo_close_path(iCairo); } void CairoPainter::doDrawArc(const Arc &arc) { cairo_save(iCairo); Matrix m = matrix() * arc.iM; cairo_matrix_t matrix; matrix.xx = m.a[0]; matrix.xy = m.a[2]; matrix.yx = m.a[1]; matrix.yy = m.a[3]; matrix.x0 = m.a[4]; matrix.y0 = m.a[5]; cairo_transform(iCairo, &matrix); if (arc.isEllipse()) { cairo_new_sub_path(iCairo); cairo_arc(iCairo, 0.0, 0.0, 1.0, 0.0, IpeTwoPi); cairo_close_path(iCairo); } else { // this is necessary because of rounding errors: // otherwise cairo may insert a near-zero-length segment that messes // up line cap if (iAfterMoveTo) cairo_new_sub_path(iCairo); cairo_arc(iCairo, 0.0, 0.0, 1.0, arc.iAlpha, arc.iBeta); } iAfterMoveTo = false; cairo_restore(iCairo); } void CairoPainter::doDrawPath(TPathMode mode) { cairo_save(iCairo); if (mode >= EStrokedAndFilled) { Color fillColor = fill(); // DimColor(qfill); cairo_set_fill_rule(iCairo, (fillRule() == EEvenOddRule) ? CAIRO_FILL_RULE_EVEN_ODD : CAIRO_FILL_RULE_WINDING); const Tiling *t = 0; if (!tiling().isNormal()) t = cascade()->findTiling(tiling()); const Gradient *g = 0; if (!gradient().isNormal()) g = cascade()->findGradient(gradient()); if (t == 0 && g == 0) { // no tiling, no gradient cairo_set_source_rgba(iCairo, fillColor.iRed.toDouble(), fillColor.iGreen.toDouble(), fillColor.iBlue.toDouble(), opacity().toDouble()); if (mode == EStrokedAndFilled) cairo_fill_preserve(iCairo); else cairo_fill(iCairo); } else if (t == 0) { // gradient cairo_pattern_t *p; if (g->iType == Gradient::ERadial) p = cairo_pattern_create_radial(g->iV[0].x, g->iV[0].y, g->iRadius[0], g->iV[1].x, g->iV[1].y, g->iRadius[1]); else p = cairo_pattern_create_linear(g->iV[0].x, g->iV[0].y, g->iV[1].x, g->iV[1].y); cairo_pattern_set_extend(p, g->iExtend ? CAIRO_EXTEND_PAD : CAIRO_EXTEND_NONE); for (uint i = 0; i < g->iStops.size(); ++i) cairo_pattern_add_color_stop_rgb(p, g->iStops[i].offset, g->iStops[i].color.iRed.toDouble(), g->iStops[i].color.iGreen.toDouble(), g->iStops[i].color.iBlue.toDouble()); const Matrix &m0 = (matrix()* g->iMatrix).inverse(); cairo_matrix_t m; m.xx = m0.a[0]; m.yx = m0.a[1]; m.xy = m0.a[2]; m.yy = m0.a[3]; m.x0 = m0.a[4]; m.y0 = m0.a[5]; cairo_pattern_set_matrix(p, &m); cairo_set_source(iCairo, p); if (mode == EStrokedAndFilled) cairo_fill_preserve(iCairo); else cairo_fill(iCairo); cairo_pattern_destroy(p); } else { // tiling cairo_surface_t *s = cairo_image_surface_create(CAIRO_FORMAT_ARGB32, 32, 32); uchar *data = cairo_image_surface_get_data(s); memset(data, 0, 4 * 32 * 32); cairo_t *cc = cairo_create(s); cairo_set_source_rgba(cc, fillColor.iRed.toDouble(), fillColor.iGreen.toDouble(), fillColor.iBlue.toDouble(), 1.0); cairo_rectangle(cc, 0, 0, 32, 32 * t->iWidth / t->iStep); cairo_fill(cc); cairo_destroy(cc); cairo_pattern_t *p = cairo_pattern_create_for_surface(s); cairo_pattern_set_extend(p, CAIRO_EXTEND_REPEAT); cairo_matrix_t m; cairo_matrix_init_scale(&m, 1.0, 32.0 / t->iStep); cairo_matrix_rotate(&m, -double(t->iAngle)); cairo_pattern_set_matrix(p, &m); cairo_set_source(iCairo, p); if (mode == EStrokedAndFilled) cairo_fill_preserve(iCairo); else cairo_fill(iCairo); cairo_pattern_destroy(p); cairo_surface_destroy(s); } } if (mode <= EStrokedAndFilled) { Color strokeColor = stroke(); // DimColor(qstroke); cairo_set_source_rgba(iCairo, strokeColor.iRed.toDouble(), strokeColor.iGreen.toDouble(), strokeColor.iBlue.toDouble(), opacity().toDouble()); cairo_set_line_width(iCairo, pen().toDouble()); switch (lineJoin()) { case EMiterJoin: cairo_set_line_join(iCairo, CAIRO_LINE_JOIN_MITER); break; case ERoundJoin: case EDefaultJoin: cairo_set_line_join(iCairo, CAIRO_LINE_JOIN_ROUND); break; case EBevelJoin: cairo_set_line_join(iCairo, CAIRO_LINE_JOIN_BEVEL); break; } switch (lineCap()) { case EButtCap: cairo_set_line_cap(iCairo, CAIRO_LINE_CAP_BUTT); break; case ERoundCap: case EDefaultCap: cairo_set_line_cap(iCairo, CAIRO_LINE_CAP_ROUND); break; case ESquareCap: cairo_set_line_cap(iCairo, CAIRO_LINE_CAP_SQUARE); break; } if (dashStyle() != "[]0") { std::vector dashes; double offset; dashStyle(dashes, offset); cairo_set_dash(iCairo, &dashes[0], dashes.size(), offset); } cairo_stroke(iCairo); } cairo_restore(iCairo); } void CairoPainter::doAddClipPath() { cairo_clip(iCairo); } // -------------------------------------------------------------------- class RenderData : public Bitmap::MRenderData { public: virtual ~RenderData() { /* Nothing */ } Buffer pixels; }; void CairoPainter::doDrawBitmap(Bitmap bitmap) { // make caching optional, or cache only most recent bitmaps? #if 1 // The original data in the bitmap may be deflated or dct encoded // cache the decoded data for faster rendering if (!bitmap.renderData()) { RenderData *render = new RenderData; render->pixels = bitmap.pixelData(); // empty if failed // may need to scale down? bitmap.setRenderData(render); } if (!bitmap.renderData()) return; RenderData *render = static_cast(bitmap.renderData()); Buffer data = render->pixels; #else Buffer data = bitmap.pixelData(); #endif if (!data.size()) return; // is this legal? I don't want cairo to modify my bitmap temporarily. cairo_surface_t *image = cairo_image_surface_create_for_data((uchar *) data.data(), CAIRO_FORMAT_ARGB32, bitmap.width(), bitmap.height(), 4 * bitmap.width()); cairo_save(iCairo); Matrix tf = matrix() * Matrix(1.0 / bitmap.width(), 0.0, 0.0, -1.0 / bitmap.height(), 0.0, 1.0); cairo_matrix_t matrix; matrix.xx = tf.a[0]; matrix.yx = tf.a[1]; matrix.xy = tf.a[2]; matrix.yy = tf.a[3]; matrix.x0 = tf.a[4]; matrix.y0 = tf.a[5]; cairo_transform(iCairo, &matrix); cairo_set_source_surface(iCairo, image, 0, 0); cairo_pattern_set_filter(cairo_get_source(iCairo), CAIRO_FILTER_NEAREST); cairo_paint(iCairo); cairo_restore(iCairo); } void CairoPainter::doDrawText(const Text *text) { // Current origin is lower left corner of text box // Draw bounding box rectangle if (!iPretty && !iDimmed && !text->isInternal()) { cairo_save(iCairo); cairo_set_source_rgb(iCairo, 0.0, 1.0, 0.0); cairo_set_line_width(iCairo, 1.0 / iZoom); double dash = 3.0 / iZoom; cairo_set_dash(iCairo, &dash, 1, 0.0); Vector u0 = matrix() * Vector::ZERO; Vector u1 = matrix() * Vector(0, text->totalHeight()); Vector u2 = matrix() * Vector(text->width(), text->totalHeight()); Vector u3 = matrix() * Vector(text->width(), 0); cairo_move_to(iCairo, u0.x, u0.y); cairo_line_to(iCairo, u1.x, u1.y); cairo_line_to(iCairo, u2.x, u2.y); cairo_line_to(iCairo, u3.x, u3.y); cairo_close_path(iCairo); cairo_stroke(iCairo); Vector ref = matrix() * text->align(); cairo_rectangle(iCairo, ref.x - 3.0/iZoom, ref.y - 3.0/iZoom, 6.0/iZoom, 6.0/iZoom); cairo_fill(iCairo); cairo_restore(iCairo); } Color col = stroke(); iTextRgb[0] = col.iRed.toDouble(); iTextRgb[1] = col.iGreen.toDouble(); iTextRgb[2] = col.iBlue.toDouble(); // DimColor(iTextRgb); const Text::XForm *xf = text->getXForm(); if (!xf || !iFonts) { if (!text->isInternal()) { String s = text->text(); int i = s.find('\n'); if (i < 0 || i > 30) i = 30; if (i < s.size()) s = s.left(i) + "..."; Vector pt = matrix().translation(); // pt.y = pt.y - iPainter->fontMetrics().descent(); cairo_font_face_t *font = Fonts::screenFont(); if (font) { cairo_save(iCairo); cairo_set_font_face(iCairo, font); cairo_set_font_size(iCairo, 9.0); cairo_set_source_rgba(iCairo, iTextRgb[0], iTextRgb[1], iTextRgb[2], opacity().toDouble()); cairo_translate(iCairo, pt.x, pt.y); cairo_scale(iCairo, 1.0, -1.0); cairo_show_text(iCairo, s.z()); cairo_restore(iCairo); } } } else { transform(Matrix(xf->iStretch, 0, 0, xf->iStretch, 0, 0)); execute(xf->iStream); } } // -------------------------------------------------------------------- #if 0 //! If dimming, replace color by dimmed version. void CairoPainter::DimColor(QColor &col) { if (iDimmed) { int h, s, v; col.getHsv(&h, &s, &v); v += 150; if (v > 255) col = col.light(175); else col.setHsv(h, s, v); } } #endif // -------------------------------------------------------------------- //! Clear PDF argument stack void CairoPainter::clearArgs() { while (!iArgs.empty()) { delete iArgs.back(); iArgs.pop_back(); } } void CairoPainter::execute(const Buffer &buffer) { BufferSource source(buffer); PdfParser parser(source); iFont = 0; iFillRgb[0] = iFillRgb[1] = iFillRgb[2] = 0.0; iStrokeRgb[0] = iStrokeRgb[1] = iStrokeRgb[2] = 0.0; while (!parser.eos()) { PdfToken tok = parser.token(); if (tok.iType != PdfToken::EOp) { const PdfObj *obj = parser.getObject(); if (!obj) break; // no further parsing attempted iArgs.push_back(obj); } else { // its an operator, execute it String op = tok.iString; parser.getToken(); if (op == "cm") opcm(); else if (op == "q") opq(); else if (op == "Q") opQ(); else if (op == "Tf") opTf(); else if (op == "Td") opTd(); else if (op == "TJ") opTJ(); else if (op == "rg") oprg(false); else if (op == "RG") oprg(true); else if (op == "g") opg(false); else if (op == "G") opg(true); else if (op == "k") opk(false); else if (op == "K") opk(true); else if (op == "w") opw(); else if (op == "m") opm(); else if (op == "l") opl(); else if (op == "re") opre(); else if (op == "sym") opsym(); else if (op == "BT") opBT(); else if (op != "ET") { String a; for (uint i = 0; i < iArgs.size(); ++i) a += iArgs[i]->repr() + " "; ipeDebug("op %s (%s)", op.z(), a.z()); } clearArgs(); } } clearArgs(); } void CairoPainter::opg(bool stroke) { if (iArgs.size() != 1 || !iArgs[0]->number()) return; double gr = iArgs[0]->number()->value(); if (stroke) iStrokeRgb[0] = iStrokeRgb[1] = iStrokeRgb[2] = gr; else iFillRgb[0] = iFillRgb[1] = iFillRgb[2] = gr; } void CairoPainter::oprg(bool stroke) { if (iArgs.size() != 3 || !iArgs[0]->number() || !iArgs[1]->number() || !iArgs[2]->number()) return; double *col = (stroke ? iStrokeRgb : iFillRgb); for (int i = 0; i < 3; ++i) col[i] = iArgs[i]->number()->value(); // Dimcolor? } void CairoPainter::opk(bool stroke) { if (iArgs.size() != 4 || !iArgs[0]->number() || !iArgs[1]->number() || !iArgs[2]->number() || !iArgs[3]->number()) return; // ignore values, but use text object stroke color double *col = (stroke ? iStrokeRgb : iFillRgb); for (int i = 0; i < 3; ++i) col[i] = iTextRgb[i]; } void CairoPainter::opcm() { if (iArgs.size() != 6) return; Matrix m; for (int i = 0; i < 6; ++i) { if (!iArgs[i]->number()) return; m.a[i] = iArgs[i]->number()->value(); } transform(m); } void CairoPainter::opw() { if (iArgs.size() != 1 || !iArgs[0]->number()) return; iLineWid = iArgs[0]->number()->value(); } void CairoPainter::opq() { if (iArgs.size() != 0) return; push(); pushMatrix(); } void CairoPainter::opQ() { if (iArgs.size() != 0) return; popMatrix(); pop(); } void CairoPainter::opm() { if (iArgs.size() != 2 || !iArgs[0]->number() || !iArgs[1]->number()) return; Vector t(iArgs[0]->number()->value(), iArgs[1]->number()->value()); iMoveTo = t; } void CairoPainter::opl() { if (iArgs.size() != 2 || !iArgs[0]->number() || !iArgs[1]->number()) return; Vector t(iArgs[0]->number()->value(), iArgs[1]->number()->value()); cairo_set_source_rgb(iCairo, iStrokeRgb[0], iStrokeRgb[1], iStrokeRgb[2]); cairo_set_line_width(iCairo, iLineWid); Vector u0 = matrix() * iMoveTo; Vector u1 = matrix() * t; cairo_move_to(iCairo, u0.x, u0.y); cairo_line_to(iCairo, u1.x, u1.y); cairo_stroke(iCairo); } void CairoPainter::opsym() { if (iArgs.size() != 5) return; String s[5]; for (int i = 0; i < 5; ++i) { if (!iArgs[i]->string()) return; s[i] = iArgs[i]->string()->value(); } // ipeDebug("render Symbol %s, %s, %s, %s, %s", // s[0].z(), s[1].z(), s[2].z(), s[3].z(), s[4].z()); const Symbol *symbol = cascade()->findSymbol(Attribute(true, s[0])); if (symbol) { pushMatrix(); push(); untransform(symbol->iTransformations); double sa = Lex(s[1]).getDouble(); Matrix m(sa, 0, 0, sa, 0, 0); transform(m); setSymStroke(Attribute::makeColor(s[2], Attribute::BLACK())); setSymFill(Attribute::makeColor(s[3], Attribute::WHITE())); setSymPen(Attribute::makeScalar(s[4], Attribute::NORMAL())); symbol->iObject->draw(*this); pop(); popMatrix(); } } void CairoPainter::opre() { if (iArgs.size() != 4 || !iArgs[0]->number() || !iArgs[1]->number() || !iArgs[2]->number() || !iArgs[3]->number()) return; Vector t(iArgs[0]->number()->value(), iArgs[1]->number()->value()); Vector wh(iArgs[2]->number()->value(), iArgs[3]->number()->value()); cairo_set_source_rgb(iCairo, iFillRgb[0], iFillRgb[1], iFillRgb[2]); Vector t1 = matrix() * t; Vector wh1 = matrix().linear() * wh; cairo_rectangle(iCairo, t1.x, t1.y, wh1.x, wh1.y); cairo_fill(iCairo); } void CairoPainter::opBT() { iFont = 0; iTextPos = iTextLinePos = Vector::ZERO; } void CairoPainter::opTf() { if (iArgs.size() != 2 || !iArgs[0]->name() || !iArgs[1]->number()) return; String name = iArgs[0]->name()->value(); iFontSize = iArgs[1]->number()->value(); if (name[0] != 'F') return; int font = Lex(name.substr(1)).getInt(); iFont = iFonts->getFace(font); iFontMatrix = matrix().linear() * Linear(iFontSize, 0, 0, -iFontSize); } void CairoPainter::opTd() { if (iArgs.size() != 2 || !iArgs[0]->number() || !iArgs[1]->number()) return; Vector t(iArgs[0]->number()->value(), iArgs[1]->number()->value()); iTextPos = iTextLinePos = iTextLinePos + t; } void CairoPainter::opTJ() { if (!iFont || iArgs.size() != 1 || !iArgs[0]->array()) return; std::vector glyphs; for (int i = 0; i < iArgs[0]->array()->count(); ++i) { const PdfObj *obj = iArgs[0]->array()->obj(i, 0); if (obj->number()) { iTextPos.x -= 0.001 * iFontSize * obj->number()->value(); } else if (obj->string()) { String s = obj->string()->value(); for (int j = 0; j < s.size(); ++j) { uchar ch = s[j]; Vector pt = matrix() * iTextPos; cairo_glyph_t g; g.index = iFont->getGlyph(ch); g.x = pt.x; g.y = pt.y; glyphs.push_back(g); iTextPos.x += 0.001 * iFontSize * iFont->width(ch); } } } drawGlyphs(glyphs); } // -------------------------------------------------------------------- //! Draw a glyph. /*! Glyph is drawn with hotspot at position pos. */ void CairoPainter::drawGlyphs(std::vector &glyphs) { if (!iFont) return; cairo_matrix_t matrix; matrix.xx = iFontMatrix.a[0]; matrix.yx = iFontMatrix.a[1]; matrix.xy = iFontMatrix.a[2]; matrix.yy = iFontMatrix.a[3]; matrix.x0 = 0.0; matrix.y0 = 0.0; cairo_save(iCairo); cairo_set_font_face(iCairo, iFont->cairoFont()); cairo_set_font_matrix(iCairo, &matrix); cairo_set_source_rgba(iCairo, iFillRgb[0], iFillRgb[1], iFillRgb[2], opacity().toDouble()); cairo_show_glyphs(iCairo, &glyphs[0], glyphs.size()); cairo_restore(iCairo); } // -------------------------------------------------------------------- ipe-7.1.4/src/ipecairo/ipefonts.cpp0000644000175000017500000002770312120621776017104 0ustar otfriedotfried// -------------------------------------------------------------------- // Rendering fonts onto the canvas // -------------------------------------------------------------------- /* This file is part of the extensible drawing editor Ipe. Copyright (C) 1993-2013 Otfried Cheong Ipe is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. As a special exception, you have permission to link Ipe with the CGAL library and distribute executables, as long as you follow the requirements of the Gnu General Public License in regard to all of the software in the executable aside from CGAL. Ipe 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 General Public License for more details. You should have received a copy of the GNU General Public License along with Ipe; if not, you can find it at "http://www.gnu.org/copyleft/gpl.html", or write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ #include "ipefonts.h" #include "ipefontpool.h" #include "ipepdfparser.h" #include "ipexml.h" #include #include FT_FREETYPE_H #undef CAIRO_HAS_FC_FONT #include #ifdef WIN32XX extern "C" cairo_font_face_t * _cairo_font_face_twin_create(cairo_font_slant_t slant, cairo_font_weight_t weight); #endif using namespace ipe; extern bool getStdFontWidths(String fontName, const String encoding[0x100], int width[0x100]); // -------------------------------------------------------------------- static const char * const stdFontMap[] = { "Times-Roman", "Times-Italic", "Times-Bold", "Times-BoldItalic", "Helvetica", "Helvetica-Oblique", "Helvetica-Bold", "Helvetica-BoldOblique", "Courier", "Courier-Oblique", "Courier-Bold", "Courier-BoldOblique", "Symbol", "ZapfDingbats", }; static const char * const stdFontMapAlias[] = { "NimbusRomNo9L-Regu", "NimbusRomNo9L-ReguItal", "NimbusRomNo9L-Medi", "NimbusRomNo9L-MediItal", "NimbusSanL-Regu", "NimbusSanL-ReguItal", "NimbusSanL-Bold", "NimbusSanL-BoldItal", "NimbusMonL-Regu", "NimbusMonL-ReguObli", "NimbusMonL-Bold", "NimbusMonL-BoldObli", "StandardSymL", "Dingbats", }; // -------------------------------------------------------------------- class FontmapParser : public XmlParser { public: explicit FontmapParser(DataSource &source) : XmlParser(source) { /* nothing */ } bool parseFontmap(); String iGlyphs[14]; }; // Parse a fontmap. bool FontmapParser::parseFontmap() { XmlAttributes att; String tag = parseToTag(); if (tag == "?xml") { if (!parseAttributes(att, true)) return false; tag = parseToTag(); } if (tag != "fontmap") return false; if (!parseAttributes(att)) return false; tag = parseToTag(); while (tag == "font") { if (!parseAttributes(att)) return false; if (att["format"] == "type1") { String name = att["name"]; String glyphs = att["glyphs"]; int i = 0; while (i < 14 && name != String(stdFontMap[i]) && name != String(stdFontMapAlias[i])) ++i; if (i < 14) iGlyphs[i] = glyphs; } tag = parseToTag(); } if (tag != "/fontmap") return false; return true; } // -------------------------------------------------------------------- struct Engine { public: Engine(); ~Engine(); Buffer standardFont(String name); cairo_font_face_t *screenFont(); private: void findStandardFonts(); bool iFontMapLoaded; bool iScreenFontLoaded; String iStandardFont[14]; Buffer iStandardFontBuffer[14]; cairo_font_face_t *iScreenFont; public: bool iOk; FT_Library iLib; int iFacesLoaded; int iFacesUnloaded; int iFacesDiscarded; }; // Auto-constructed and destructed Freetype engine. static Engine engine; // -------------------------------------------------------------------- Engine::Engine() { iOk = false; iFontMapLoaded = false; iScreenFont = 0; iScreenFontLoaded = false; iFacesLoaded = 0; iFacesUnloaded = 0; iFacesDiscarded = 0; if (FT_Init_FreeType(&iLib)) return; iOk = true; } Engine::~Engine() { ipeDebug("Freetype engine: %d faces loaded, %d faces unloaded, " "%d faces discarded", iFacesLoaded, iFacesUnloaded, iFacesDiscarded); if (iScreenFont) cairo_font_face_destroy(iScreenFont); if (iOk) FT_Done_FreeType(iLib); // causes an assert in cairo to fail: // cairo_debug_reset_static_data(); ipeDebug("Freetype engine: %d faces discarded", iFacesDiscarded); } // -------------------------------------------------------------------- //! Parse the fontmap and store absolute paths for standard fonts. void Engine::findStandardFonts() { iFontMapLoaded = true; String fm = Platform::fontmapFile(); int i = fm.rfind(Platform::pathSeparator()); String fmb = fm.left(i+1); std::FILE *file = std::fopen(fm.z(), "rb"); if (!file) { ipeDebug("Could not open fontmap '%s'", fm.z()); return; } FileSource source(file); FontmapParser parser(source); if (parser.parseFontmap()) { for (int i = 0; i < 14; ++i) { if (!parser.iGlyphs[i].empty()) { String fname = parser.iGlyphs[i]; // make relative paths based on fmb #ifdef __MINGW32__ if (fname[0] != '\\' && fname[1] != ':') fname = fmb + fname; #else if (fname[0] != '/') fname = fmb + fname; #endif if (Platform::fileExists(fname)) iStandardFont[i] = fname; } } } else ipeDebug("Could not parse fontmap."); std::fclose(file); for (int i = 0; i < 14; ++i) { if (iStandardFont[i].empty()) { ipeDebug("No font file found for '%s'", stdFontMap[i]); } else { ipeDebug("Standard font '%s' uses font file '%s", stdFontMap[i], iStandardFont[i].z()); } } } //! Return contents of font file for standard font \a name. Buffer Engine::standardFont(String name) { if (!iFontMapLoaded) findStandardFonts(); for (int i = 0; i < 14; ++i) { if (name == stdFontMap[i]) { // if it's known and not yet loaded, load it if (!iStandardFont[i].empty() && iStandardFontBuffer[i].size() == 0) { String s = Platform::readFile(iStandardFont[i]); iStandardFontBuffer[i] = Buffer(s.data(), s.size()); } return iStandardFontBuffer[i]; } } return Buffer(); } cairo_font_face_t *Engine::screenFont() { if (!iScreenFontLoaded) { iScreenFontLoaded = true; #ifdef WIN32XX iScreenFont = _cairo_font_face_twin_create(CAIRO_FONT_SLANT_NORMAL, CAIRO_FONT_WEIGHT_BOLD); #else iScreenFont = cairo_toy_font_face_create("Sans", CAIRO_FONT_SLANT_NORMAL, CAIRO_FONT_WEIGHT_BOLD); // Alternative (in Cairo 1.6): // FcPattern *pat = FcFontMatch(NULL, FcNameParse((FcChar8 *) "Sans"), 0); // iScreenFont = cairo_ft_font_face_create_for_pattern(pat); #endif } return iScreenFont; } // -------------------------------------------------------------------- /*! \class ipe::Fonts \ingroup cairo \brief Provides the fonts used to render text. */ Fonts *Fonts::New(const FontPool *fontPool) { if (!engine.iOk) return 0; return new Fonts(fontPool); } //! Private constructor Fonts::Fonts(const FontPool *fontPool) : iFontPool(fontPool) { // nothing } //! Delete all the loaded Faces. Fonts::~Fonts() { for (FaceSeq::iterator it = iFaces.begin(); it != iFaces.end(); ++it) delete *it; } String Fonts::freetypeVersion() { int major, minor, patch; FT_Library_Version(engine.iLib, &major, &minor, &patch); char buf[128]; sprintf(buf, "Freetype %d.%d.%d / %d.%d.%d", FREETYPE_MAJOR, FREETYPE_MINOR, FREETYPE_PATCH, major, minor, patch); ipeDebug("Using %s", buf); return String(buf); } //! Return a Cairo font to render to the screen w/o Latex font. cairo_font_face_t *Fonts::screenFont() { return engine.screenFont(); } //! Get a typeface. /*! Corresponds to a Freetype "face", or a PDF font resource. A Face can be loaded at various sizes (transformations), resulting in individual FaceSize's. */ Face *Fonts::getFace(int id) { for (FaceSeq::iterator it = iFaces.begin(); it != iFaces.end(); ++it) { if ((*it)->matches(id)) return *it; } // need to create it std::vector::const_iterator it = iFontPool->begin(); while (it != iFontPool->end() && it->iLatexNumber != id) ++it; if (it == iFontPool->end()) return 0; Face *face = new Face(id, *it); iFaces.push_back(face); return face; } // -------------------------------------------------------------------- struct FaceData { Buffer iData; FT_Face iFace; }; static void face_data_destroy(FaceData *face_data) { ++engine.iFacesDiscarded; FT_Done_Face(face_data->iFace); // discard Freetype face delete face_data; // discard memory buffer } static const cairo_user_data_key_t key = { 0 }; /*! \class ipe::Face \ingroup cairo \brief A typeface (aka font), actually loaded (from a font file or PDF file). */ Face::Face(int id, const Font &font) { ipeDebug("Loading face '%s' for id %d", font.iName.z(), id); iId = id; iType = font.iType; iCairoFont = 0; for (int i = 0; i < 0x100; ++i) { iGlyphIndex[i] = 0; iWidth[i] = 0; } Buffer data; FT_Face face; if (!font.iStandardFont) { for (int i = 0; i < 0x100; ++i) iWidth[i] = font.iWidth[i]; data = font.iStreamData; if (FT_New_Memory_Face(engine.iLib, (const uchar *) data.data(), data.size(), 0, &face)) return; } else { if (!getStdFontWidths(font.iName, font.iEncoding, iWidth)) return; data = engine.standardFont(font.iName); if (data.size() == 0 || FT_New_Memory_Face(engine.iLib, (const uchar *) data.data(), data.size(), 0, &face)) return; } FaceData *face_data = new FaceData; face_data->iData = data; face_data->iFace = face; // see cairo_ft_font_face_create_for_ft_face docs iCairoFont = cairo_ft_font_face_create_for_ft_face(face, 0); cairo_status_t status = cairo_font_face_set_user_data(iCairoFont, &key, face_data, (cairo_destroy_func_t) face_data_destroy); if (status) { ipeDebug("Failed to set user data for Cairo font"); cairo_font_face_destroy(iCairoFont); FT_Done_Face(face); delete face_data; return; } ++engine.iFacesLoaded; if (iType == Font::EType1) { if (font.iHasEncoding) { for (int i = 0; i < 0x100; ++i) iGlyphIndex[i] = FT_Get_Name_Index(face, const_cast(font.iEncoding[i].z())); } else { for (int k = 0; k < face->num_charmaps; ++k) { if (face->charmaps[k]->encoding == FT_ENCODING_ADOBE_CUSTOM) { FT_Set_Charmap(face, face->charmaps[k]); break; } } // Otherwise need to check FT_Has_PS_Glyph_Names(iFace)? for (int i = 0; i < 0x100; ++i) iGlyphIndex[i] = FT_Get_Char_Index(face, i); } } else { // Truetype font, don't use /Encoding (shouldn't have one) FT_Set_Charmap(face, face->charmaps[0]); if (face->charmaps[0]->platform_id != 1 || face->charmaps[0]->encoding_id != 0) { ipeDebug("TrueType face %d has strange first charmap (of %d)", iId, face->num_charmaps); for (int i = 0; i < face->num_charmaps; ++i) { ipeDebug("Map %d has platform %d, encoding %d", i, face->charmaps[i]->platform_id, face->charmaps[i]->encoding_id); } } } } Face::~Face() { ipeDebug("Done with Cairo face %d (%d references left)", iId, cairo_font_face_get_reference_count(iCairoFont)); if (iCairoFont) { ++engine.iFacesUnloaded; cairo_font_face_destroy(iCairoFont); } } int Face::getGlyph(int ch) { FaceData *face_data = (FaceData *) cairo_font_face_get_user_data(iCairoFont, &key); if (!face_data->iFace) // face is not available return 0; if (type() == Font::EType1) return iGlyphIndex[ch]; else return FT_Get_Char_Index(face_data->iFace, (FT_ULong) ch); } // -------------------------------------------------------------------- ipe-7.1.4/src/ipecairo/ipethumbs.cpp0000644000175000017500000000540012120621776017243 0ustar otfriedotfried// -------------------------------------------------------------------- // Making thumbnails of Ipe pages // -------------------------------------------------------------------- /* This file is part of the extensible drawing editor Ipe. Copyright (C) 1993-2013 Otfried Cheong Ipe is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. As a special exception, you have permission to link Ipe with the CGAL library and distribute executables, as long as you follow the requirements of the Gnu General Public License in regard to all of the software in the executable aside from CGAL. Ipe 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 General Public License for more details. You should have received a copy of the GNU General Public License along with Ipe; if not, you can find it at "http://www.gnu.org/copyleft/gpl.html", or write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ #include "ipethumbs.h" #include "ipecairopainter.h" #include using namespace ipe; // -------------------------------------------------------------------- Thumbnail::Thumbnail(const Document *doc, int width) { iDoc = doc; iWidth = width; iLayout = iDoc->cascade()->findLayout(); Rect paper = iLayout->paper(); iHeight = int(iWidth * paper.height() / paper.width()); iZoom = iWidth / paper.width(); ipeDebug("%g %g -> %d %d", paper.width(), paper.height(), iWidth, iHeight); iFonts = Fonts::New(doc->fontPool()); } Thumbnail::~Thumbnail() { delete iFonts; } Buffer Thumbnail::render(const Page *page, int view) { Buffer buffer(iWidth * iHeight * 4); memset(buffer.data(), 0xff, iWidth * iHeight * 4); cairo_surface_t* surface = cairo_image_surface_create_for_data((uchar *) buffer.data(), CAIRO_FORMAT_ARGB32, iWidth, iHeight, iWidth * 4); cairo_t *cc = cairo_create(surface); cairo_scale(cc, iZoom, -iZoom); Vector offset = iLayout->iOrigin - iLayout->paper().topLeft(); cairo_translate(cc, offset.x, offset.y); CairoPainter painter(iDoc->cascade(), iFonts, cc, iZoom, true); painter.pushMatrix(); for (int i = 0; i < page->count(); ++i) { if (page->objectVisible(view, i)) page->object(i)->draw(painter); } painter.popMatrix(); cairo_surface_flush(surface); cairo_show_page(cc); cairo_destroy(cc); cairo_surface_destroy(surface); return buffer; } // -------------------------------------------------------------------- ipe-7.1.4/src/include/0000755000175000017500000000000012120621776014370 5ustar otfriedotfriedipe-7.1.4/src/include/ipeattributes.h0000644000175000017500000003550112120621776017431 0ustar otfriedotfried// -*- C++ -*- // -------------------------------------------------------------------- // Ipe object attributes // -------------------------------------------------------------------- /* This file is part of the extensible drawing editor Ipe. Copyright (C) 1993-2013 Otfried Cheong Ipe is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. As a special exception, you have permission to link Ipe with the CGAL library and distribute executables, as long as you follow the requirements of the Gnu General Public License in regard to all of the software in the executable aside from CGAL. Ipe 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 General Public License for more details. You should have received a copy of the GNU General Public License along with Ipe; if not, you can find it at "http://www.gnu.org/copyleft/gpl.html", or write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ #ifndef IPEATTRIBUTES_H #define IPEATTRIBUTES_H #include "ipebase.h" #include "ipegeo.h" // -------------------------------------------------------------------- namespace ipe { /*! \brief The different kinds of attributes. \ingroup attr The same symbolic attribute (say "normal") has a different value in the StyleSheet depending on the Kind of attribute. The main use for Kind is as an argument to StyleSheet::find. ESymbol, EGradient, ETiling, and EEffect have their own lookup methods in the StyleSheet. The values are still useful as an argument to allNames(), has(), and findDefinition(). */ enum Kind { EPen = 0, ESymbolSize, EArrowSize, EColor, EDashStyle, ETextSize, ETextStretch, ETextStyle, EGridSize, EAngleSize, EOpacity, ETiling, ESymbol, EGradient, EEffect }; /*! \ingroup attr */ extern const char * const kind_names[]; /*! \brief A Property identifies an attribute that an object can have. \ingroup attr The Property identifies a unique attribute of an object, while different Property values can be of the same ipe::Kind. For instance, both EPropStrokeColor and EPropFillColor identify an Attribute of Kind EColor. */ enum Property { EPropPen = 0, EPropSymbolSize, EPropFArrow, EPropRArrow, EPropFArrowSize, EPropRArrowSize, EPropFArrowShape, EPropRArrowShape, EPropStrokeColor, EPropFillColor, EPropMarkShape, EPropPathMode, EPropDashStyle, EPropTextSize, EPropTextStyle, EPropOpacity, EPropTiling, EPropGradient, EPropHorizontalAlignment, EPropVerticalAlignment, EPropLineJoin, EPropLineCap, EPropFillRule, EPropPinned, EPropTransformations, EPropTransformableText, EPropMinipage, EPropWidth, }; /*! \ingroup attr */ extern const char * const property_names[]; //! Path mode (stroked, filled, or both). /*! \ingroup attr */ enum TPathMode { EStrokedOnly, EStrokedAndFilled, EFilledOnly }; //! Horizontal alignment. /*! \ingroup attr */ enum THorizontalAlignment { EAlignLeft, EAlignRight, EAlignHCenter }; //! Vertical alignment. /*! \ingroup attr */ enum TVerticalAlignment { EAlignBottom, EAlignBaseline, EAlignTop, EAlignVCenter }; //! Line join style. /*! \ingroup attr */ /*! The EDefaultJoin means to use the setting from the style sheet. */ enum TLineJoin { EDefaultJoin, EMiterJoin, ERoundJoin, EBevelJoin }; //! Line cap style. /*! \ingroup attr */ /*! The EDefaultCap means to use the setting from the style sheet. */ enum TLineCap { EDefaultCap, EButtCap, ERoundCap, ESquareCap }; //! Fill rule. /*! \ingroup attr */ /*! The EDefaultRule means to use the setting from the style sheet. */ enum TFillRule { EDefaultRule, EWindRule, EEvenOddRule }; //! Pinning status of objects. /*! \ingroup attr */ enum TPinned { ENoPin = 0x00, EHorizontalPin = 0x01, EVerticalPin = 0x02, EFixedPin = 0x03 }; //! Transformations that are permitted for an object. /*! \ingroup attr */ enum TTransformations { ETransformationsTranslations, ETransformationsRigidMotions, ETransformationsAffine }; //! Selection status of an object on the page /*! \ingroup attr */ enum TSelect { ENotSelected = 0, EPrimarySelected, ESecondarySelected }; // -------------------------------------------------------------------- class Color { public: //! Default constructor. Color() { /* nothing */ } explicit Color(String str); explicit Color(int r, int g, int b); void save(Stream &stream) const; void saveRGB(Stream &stream) const; bool isGray() const; bool operator==(const Color &rhs) const; inline bool operator!=(const Color &rhs) const {return !(*this == rhs); } public: Fixed iRed, iGreen, iBlue; }; //! A tiling pattern. /*! \ingroup attr */ struct Tiling { Angle iAngle; double iStep; double iWidth; }; //! A gradient pattern. /*! \ingroup attr */ struct Gradient { //! A color stop. struct Stop { //! Offset between 0.0 and 1.0. double offset; //! The color at this offset. Color color; }; //! There are two types of gradients, along an axis or between two circles. enum TType { EAxial = 2, ERadial = 3 }; //! The type of gradient: axial or radial. TType iType; //! The coordinates of the axis endpoints, or the two circle centers. Vector iV[2]; //! The radii of the two circles (not used for axial gradients). double iRadius[2]; //! Whether to extend the gradient beyond the endpoints. bool iExtend; //! Gradient transformation. Matrix iMatrix; //! The color stops. std::vector iStops; }; //! Layout of a Page. /*! \ingroup attr */ struct Layout { //! Create null layout. Layout() { iPaperSize.x = -1.0; } //! Is this an undefined (null) layout? bool isNull() const { return iPaperSize.x < 0.0; } //! Return rectangle describing the paper. Rect paper() const { return Rect(-iOrigin, iPaperSize - iOrigin); } //! Dimensions of the media. Vector iPaperSize; //! Origin of the Ipe coordinate system relative to the paper. Vector iOrigin; //! Size of the frame (the drawing area). Vector iFrameSize; //! Paragraph skip (between textboxes). double iParagraphSkip; //! Crop paper to drawing. bool iCrop; }; //! Padding for text bounding box. /*! \ingroup attr */ struct TextPadding { public: double iLeft, iRight, iTop, iBottom; }; struct Effect { public: //! The various fancy effects that Acrobat Reader will show. enum TEffect { ENormal, ESplitHI, ESplitHO, ESplitVI, ESplitVO, EBlindsH, EBlindsV, EBoxI, EBoxO, EWipeLR, EWipeBT, EWipeRL, EWipeTB, EDissolve, EGlitterLR, EGlitterTB, EGlitterD }; Effect(); void pageDictionary(Stream &stream) const; public: TEffect iEffect; int iTransitionTime; int iDuration; }; // -------------------------------------------------------------------- class Repository { public: static Repository *get(); static void cleanup(); String toString(int index) const; int toIndex(String str); // int getIndex(String str) const; private: Repository(); static Repository *singleton; std::vector iStrings; }; // -------------------------------------------------------------------- class Attribute { enum { EMiniMask = 0xc0000000, ETypeMask = 0xe0000000, ESymbolic = 0x80000000, EFixed = 0x40000000, EAbsolute = 0xc0000000, EEnum = 0xe0000000, EFixedMask = 0x3fffffff, ENameMask = 0x1fffffff, EWhiteValue = ((1000 << 20) + (1000 << 10) + 1000), EOneValue = EFixed|1000 }; public: //! Default constructor. explicit Attribute() { /* nothing */ } explicit Attribute(bool symbolic, String name); explicit Attribute(Fixed value); explicit Attribute(Color color); static Attribute Boolean(bool flag) { return Attribute(EEnum + flag); } explicit Attribute(THorizontalAlignment align) { iName = EEnum + align +2; } explicit Attribute(TVerticalAlignment align) { iName = EEnum + align + 5; } explicit Attribute(TLineJoin join) { iName = EEnum + join + 9; } explicit Attribute(TLineCap cap) { iName = EEnum + cap + 13; } explicit Attribute(TFillRule rule) { iName = EEnum + rule + 17; } explicit Attribute(TPinned pin) { iName = EEnum + pin + 20; } explicit Attribute(TTransformations trans) { iName = EEnum + trans + 24; } explicit Attribute(TPathMode pm) { iName = EEnum + pm + 27; } //! Is it symbolic? inline bool isSymbolic() const { return ((iName & ETypeMask) == ESymbolic); } //! Is it an absolute string value? inline bool isString() const { return ((iName & ETypeMask) == EAbsolute); } //! Is it a color? inline bool isColor() const { return ((iName & EMiniMask) == 0); } //! Is it a number? inline bool isNumber() const { return ((iName & EMiniMask) == EFixed); } //! Is it an enumeration? inline bool isEnum() const { return ((iName & ETypeMask) == EEnum); } //! Is it a boolean? inline bool isBoolean() const { return (isEnum() && 0 <= index() && index() <= 1); } //! Is it the symbolic name "normal"? inline bool isNormal() const { return (iName == ESymbolic); } //! Return index into Repository. inline int index() const { return iName & ENameMask; } int internal() const { return iName; } String string() const; Fixed number() const; Color color() const; bool boolean() const { return bool(index()); } THorizontalAlignment horizontalAlignment() const { return THorizontalAlignment(index() - 2); } TVerticalAlignment verticalAlignment() const { return TVerticalAlignment(index() - 5); } TLineJoin lineJoin() const {return TLineJoin(index() - 9); } TLineCap lineCap() const { return TLineCap(index() - 13); } TFillRule fillRule() const { return TFillRule(index() - 17); } TPinned pinned() const { return TPinned(index() - 20); } TTransformations transformations() const { return TTransformations(index() - 24); } TPathMode pathMode() const { return TPathMode(index() - 27); } //! Are two values equal (only compares index!) inline bool operator==(const Attribute &rhs) const { return iName == rhs.iName; } //! Are two values different (only compares index!) inline bool operator!=(const Attribute &rhs) const { return iName != rhs.iName; } //! Create absolute black color. inline static Attribute BLACK() { return Attribute(0); } //! Create absolute white color. inline static Attribute WHITE() { return Attribute(EWhiteValue); } //! Create absolute number one. inline static Attribute ONE() { return Attribute(EOneValue); } //! Create symbolic attribute "normal". inline static Attribute NORMAL() { return Attribute(ESymbolic); } //! Create symbolic attribute "undefined" inline static Attribute UNDEFINED() { return Attribute(ESymbolic + 1); } //! Create symbolic attribute "Background" inline static Attribute BACKGROUND() { return Attribute(ESymbolic + 2); } //! Create symbolic attribute "sym-stroke" inline static Attribute SYM_STROKE() { return Attribute(ESymbolic + 3); } //! Create symbolic attribute "sym-fill" inline static Attribute SYM_FILL() { return Attribute(ESymbolic + 4); } //! Create symbolic attribute "sym-pen" inline static Attribute SYM_PEN() { return Attribute(ESymbolic + 5); } //! Create symbolic attribute "arrow/normal(spx)" inline static Attribute ARROW_NORMAL() { return Attribute(ESymbolic + 6); } //! Create symbolic attribute "opaque" inline static Attribute OPAQUE() { return Attribute(ESymbolic + 7); } //! Create symbolic attribute "arrow/arc(spx)" inline static Attribute ARROW_ARC() { return Attribute(ESymbolic + 8); } //! Create symbolic attribute "arrow/farc(spx)" inline static Attribute ARROW_FARC() { return Attribute(ESymbolic + 9); } static Attribute makeColor(String str, Attribute deflt); static Attribute makeScalar(String str, Attribute deflt); static Attribute makeDashStyle(String str); static Attribute makeTextSize(String str); static Attribute normal(Kind kind); private: inline Attribute(int index) : iName(index) { /* nothing */ } explicit Attribute(bool symbolic, int index); private: unsigned int iName; friend class StyleSheet; }; /*! \var AttributeSeq \ingroup attr \brief A sequence of attribute values. */ typedef std::vector AttributeSeq; // -------------------------------------------------------------------- class AllAttributes { public: AllAttributes(); TPathMode iPathMode; //!< Should we stroke and/or fill? Attribute iStroke; //!< Stroke color. Attribute iFill; //!< Fill color. Attribute iDashStyle; //!< Dash style. Attribute iPen; //!< Pen (that is, line width). bool iFArrow; //!< Arrow forward? bool iRArrow; //!< Reverse arrow? Attribute iFArrowShape; //!< Shape of forward arrows Attribute iRArrowShape; //!< Shape of reverse arrows Attribute iFArrowSize; //!< Forward arrow size. Attribute iRArrowSize; //!< Reverse arrow size. Attribute iSymbolSize; //!< Symbol size. Attribute iTextSize; //!< Text size. //! Horizontal alignment of label objects. THorizontalAlignment iHorizontalAlignment; //! Vertical alignment of label objects. TVerticalAlignment iVerticalAlignment; Attribute iTextStyle; //!< Text style. TPinned iPinned; //!< Pinned status. //! Should newly created text be transformable? /*! If this is false, newly created text will only allow translations. Otherwise, the value of iTranslations is used (as for other objects). */ bool iTransformableText; //! Allowed transformations. TTransformations iTransformations; TLineJoin iLineJoin; //!< Line join style. TLineCap iLineCap; //!< Line cap style. TFillRule iFillRule; //!< Shape fill rule. Attribute iOpacity; //!< Opacity. Attribute iTiling; //!< Tiling pattern. Attribute iGradient; //!< Gradient pattern. Attribute iMarkShape; //!< Shape of Mark to create. }; // -------------------------------------------------------------------- /*! \relates Color */ inline Stream &operator<<(Stream &stream, const Color &attr) { attr.save(stream); return stream; } } // namespace // -------------------------------------------------------------------- #endif ipe-7.1.4/src/include/ipelib.h0000644000175000017500000000335212120621776016010 0ustar otfriedotfried// -*- C++ -*- // -------------------------------------------------------------------- // Includes everything to handle Ipe objects, pages, and documents // -------------------------------------------------------------------- /* This file is part of the extensible drawing editor Ipe. Copyright (C) 1993-2013 Otfried Cheong Ipe is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. As a special exception, you have permission to link Ipe with the CGAL library and distribute executables, as long as you follow the requirements of the Gnu General Public License in regard to all of the software in the executable aside from CGAL. Ipe 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 General Public License for more details. You should have received a copy of the GNU General Public License along with Ipe; if not, you can find it at "http://www.gnu.org/copyleft/gpl.html", or write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ #ifndef IPELIB_H #define IPELIB_H // -------------------------------------------------------------------- #include "ipebase.h" #include "ipegeo.h" #include "ipepath.h" #include "ipetext.h" #include "ipeimage.h" #include "ipereference.h" #include "ipegroup.h" #include "ipepage.h" #include "ipedoc.h" #include "ipelet.h" #include "ipesnap.h" // -------------------------------------------------------------------- #endif ipe-7.1.4/src/include/ipexml.h0000644000175000017500000000602112120621776016036 0ustar otfriedotfried// -*- C++ -*- // -------------------------------------------------------------------- // XML parsing // -------------------------------------------------------------------- /* This file is part of the extensible drawing editor Ipe. Copyright (C) 1993-2013 Otfried Cheong Ipe is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. As a special exception, you have permission to link Ipe with the CGAL library and distribute executables, as long as you follow the requirements of the Gnu General Public License in regard to all of the software in the executable aside from CGAL. Ipe 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 General Public License for more details. You should have received a copy of the GNU General Public License along with Ipe; if not, you can find it at "http://www.gnu.org/copyleft/gpl.html", or write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ #ifndef IPEXML_H #define IPEXML_H #include "ipebase.h" // -------------------------------------------------------------------- namespace ipe { class XmlAttributes { private: typedef std::map Map; public: //! Iterator for (key, value) pairs. typedef Map::const_iterator const_iterator; //! Return const iterator for first attribute. const_iterator begin() const { return iMap.begin(); } //! Return const iterator for end of attributes. const_iterator end() const { return iMap.end(); } XmlAttributes(); void clear(); String operator[](String str) const; bool has(String str) const; bool has(String str, String &val) const; void add(String key, String val); //! Set that the tag contains the final /. inline void setSlash() { iSlash = true; } //! Return whether tag contains the final /. inline bool slash() const { return iSlash; } private: Map iMap; bool iSlash; }; class XmlParser { public: XmlParser(DataSource &source); virtual ~XmlParser(); int parsePosition() const { return iPos; } String parseToTag(); bool parseAttributes(XmlAttributes &attr, bool qm = false); bool parsePCDATA(String tag, String &pcdata); inline bool isTagChar(int ch) { return ('a' <= ch && ch <= 'z') || ('A' <= ch && ch <= 'Z') || ch == '-'; } inline void getChar() { iCh = iSource.getChar(); ++iPos; } inline bool eos() { return (iCh == EOF); } void skipWhitespace(); protected: String parseToTagX(); protected: DataSource &iSource; String iTopElement; int iCh; // current character int iPos; // position in input stream }; } // namespace // -------------------------------------------------------------------- #endif ipe-7.1.4/src/include/ipeiml.h0000644000175000017500000000433612120621776016026 0ustar otfriedotfried// -*- C++ -*- // -------------------------------------------------------------------- // Parse an Ipe XML file // -------------------------------------------------------------------- /* This file is part of the extensible drawing editor Ipe. Copyright (C) 1993-2013 Otfried Cheong Ipe is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. As a special exception, you have permission to link Ipe with the CGAL library and distribute executables, as long as you follow the requirements of the Gnu General Public License in regard to all of the software in the executable aside from CGAL. Ipe 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 General Public License for more details. You should have received a copy of the GNU General Public License along with Ipe; if not, you can find it at "http://www.gnu.org/copyleft/gpl.html", or write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ #ifndef IPEIML_H #define IPEIML_H #include "ipegroup.h" #include "ipepage.h" #include "ipedoc.h" #include "ipebitmap.h" // -------------------------------------------------------------------- namespace ipe { class ImlParser : public XmlParser { public: enum Errors { ESuccess = 0, EVersionTooOld, EVersionTooRecent, ESyntaxError }; explicit ImlParser(DataSource &source); int parseDocument(Document &doc); bool parsePage(Page &page); Object *parseObject(String tag, Page *page = 0, int *currentLayer = 0); StyleSheet *parseStyleSheet(); bool parseStyle(StyleSheet &sheet); // bool parseSelection(PageObjectSeq &seq); Page *parsePageSelection(); virtual Buffer pdfStream(int objNum); bool parseBitmap(); bool parseFontmap(String *stdNames, String *paths); private: std::vector iBitmaps; }; } // namespace // -------------------------------------------------------------------- #endif ipe-7.1.4/src/include/ipestyle.h0000644000175000017500000001532012120621776016400 0ustar otfriedotfried// -*- C++ -*- // -------------------------------------------------------------------- // Ipe style sheet // -------------------------------------------------------------------- /* This file is part of the extensible drawing editor Ipe. Copyright (C) 1993-2013 Otfried Cheong Ipe is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. As a special exception, you have permission to link Ipe with the CGAL library and distribute executables, as long as you follow the requirements of the Gnu General Public License in regard to all of the software in the executable aside from CGAL. Ipe 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 General Public License for more details. You should have received a copy of the GNU General Public License along with Ipe; if not, you can find it at "http://www.gnu.org/copyleft/gpl.html", or write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ #ifndef IPESTYLE_H #define IPESTYLE_H #include "ipeattributes.h" #include "ipetext.h" // -------------------------------------------------------------------- namespace ipe { struct Symbol { Symbol(); Symbol(Object *object); Symbol(const Symbol &rhs); Symbol &operator=(const Symbol &rhs); ~Symbol(); bool iXForm; TTransformations iTransformations; Object *iObject; }; class StyleSheet { public: //! Style of the title on a page. struct TitleStyle { //! Has a TitleStyle been defined in the style sheet? bool iDefined; //! Position on the page (in Ipe coordinate system) Vector iPos; //! Text size. Attribute iSize; //! Text color. Attribute iColor; //! Horizontal alignment. THorizontalAlignment iHorizontalAlignment; //! Vertical alignment. TVerticalAlignment iVerticalAlignment; }; //! How to show page numbers on the paper. struct PageNumberStyle { //! Has a PageNumberStyle been defined in the style sheet? bool iDefined; //! Position on the page Vector iPos; //! Font size. double iFontSize; //! Text color. Color iColor; }; StyleSheet(); static StyleSheet *standard(); void addSymbol(Attribute name, const Symbol &symbol); const Symbol *findSymbol(Attribute sym) const; void addGradient(Attribute name, const Gradient &s); const Gradient *findGradient(Attribute sym) const; void addTiling(Attribute name, const Tiling &s); const Tiling *findTiling(Attribute sym) const; void addEffect(Attribute name, const Effect &e); const Effect *findEffect(Attribute sym) const; void add(Kind kind, Attribute name, Attribute value); bool has(Kind kind, Attribute sym) const; Attribute find(Kind, Attribute sym) const; void saveAsXml(Stream &stream, bool saveBitmaps = false) const; void allNames(Kind kind, AttributeSeq &seq) const; //! Return whether this is the standard style sheet built into Ipe. inline bool isStandard() const { return iStandard; } //! Return Latex preamble. inline String preamble() const { return iPreamble; } //! Set LaTeX preamble. inline void setPreamble(const String &str) { iPreamble = str; } //! Return Latex encoding. inline String encoding() const { return iEncoding; } //! Set Latex encoding inline void setEncoding(const String &enc) { iEncoding = enc; } const Layout *layout() const; void setLayout(const Layout &margins); const TextPadding *textPadding() const; void setTextPadding(const TextPadding &pad); const TitleStyle *titleStyle() const; void setTitleStyle(const TitleStyle &ts); const PageNumberStyle *pageNumberStyle(); void setPageNumberStyle(const PageNumberStyle &pns); void addCMap(String s); void allCMaps(std::vector &seq) const; void setLineCap(TLineCap s); void setLineJoin(TLineJoin s); void setFillRule(TFillRule s); //! Return line cap. TLineCap lineCap() const { return iLineCap; } //! Return line join. TLineJoin lineJoin() const { return iLineJoin; } //! Return path fill rule. TFillRule fillRule() const { return iFillRule; } //! Return name of style sheet. inline String name() const { return iName; } //! Set name of style sheet. inline void setName(const String &name) { iName = name; } private: typedef std::map SymbolMap; typedef std::map GradientMap; typedef std::map TilingMap; typedef std::map EffectMap; typedef std::map Map; bool iStandard; String iName; SymbolMap iSymbols; GradientMap iGradients; TilingMap iTilings; EffectMap iEffects; Map iMap; String iEncoding; String iPreamble; Layout iLayout; TextPadding iTextPadding; TitleStyle iTitleStyle; PageNumberStyle iPageNumberStyle; TLineJoin iLineJoin; TLineCap iLineCap; TFillRule iFillRule; std::vector iCMaps; }; class Cascade { public: Cascade(); Cascade(const Cascade &rhs); Cascade &operator=(const Cascade &rhs); ~Cascade(); //! Return number of style sheets. inline int count() const { return iSheets.size(); } //! Return StyleSheet at \a index. inline StyleSheet *sheet(int index) { return iSheets[index]; } void insert(int index, StyleSheet *sheet); void remove(int index); void saveAsXml(Stream &stream) const; bool has(Kind kind, Attribute sym) const; Attribute find(Kind, Attribute sym) const; const Symbol *findSymbol(Attribute sym) const; const Gradient *findGradient(Attribute sym) const; const Tiling *findTiling(Attribute sym) const; const Effect *findEffect(Attribute sym) const; const Layout *findLayout() const; const TextPadding *findTextPadding() const; const StyleSheet::TitleStyle *findTitleStyle() const; const StyleSheet::PageNumberStyle *findPageNumberStyle() const; String findPreamble() const; String findEncoding() const; TLineCap lineCap() const; TLineJoin lineJoin() const; TFillRule fillRule() const; void allNames(Kind kind, AttributeSeq &seq) const; int findDefinition(Kind kind, Attribute sym) const; void allCMaps(std::vector &seq) const; private: std::vector iSheets; }; } // namespace // -------------------------------------------------------------------- #endif ipe-7.1.4/src/include/ipepswriter.h0000644000175000017500000000501612120621776017120 0ustar otfriedotfried// -*- C++ -*- // -------------------------------------------------------------------- // Creating Postscript output // -------------------------------------------------------------------- /* This file is part of the extensible drawing editor Ipe. Copyright (C) 1993-2013 Otfried Cheong Ipe is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. As a special exception, you have permission to link Ipe with the CGAL library and distribute executables, as long as you follow the requirements of the Gnu General Public License in regard to all of the software in the executable aside from CGAL. Ipe 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 General Public License for more details. You should have received a copy of the GNU General Public License along with Ipe; if not, you can find it at "http://www.gnu.org/copyleft/gpl.html", or write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ #ifndef IPEPSWRITER_H #define IPEPSWRITER_H #include "ipebase.h" #include "ipepage.h" #include "ipedoc.h" #include "ipeimage.h" #include "ipepdfwriter.h" // -------------------------------------------------------------------- namespace ipe { struct Font; class PsPainter : public PdfPainter { public: PsPainter(const Cascade *style, Stream &stream); ~PsPainter(); protected: virtual void doNewPath(); virtual void doDrawPath(TPathMode mode); virtual void doDrawBitmap(Bitmap bitmap); virtual void doAddClipPath(); private: void strokePath(); void fillPath(bool eoFill, bool preservePath); private: int iImageNumber; }; // -------------------------------------------------------------------- class PsWriter { public: PsWriter(TellStream &stream, const Document *doc, bool noColor); ~PsWriter(); bool createHeader(int pno = 0, int vno = 0); void createPageView(int pno = 0, int vno = 0); void createXml(int compressLevel); void createTrailer(); private: void embedFont(const Font &font); private: TellStream &iStream; const Document *iDoc; bool iNoColor; }; } // namespace // -------------------------------------------------------------------- #endif ipe-7.1.4/src/include/ipeshape.h0000644000175000017500000002016712120621776016345 0ustar otfriedotfried// -*- C++ -*- // -------------------------------------------------------------------- // Drawable shapes // -------------------------------------------------------------------- /* This file is part of the extensible drawing editor Ipe. Copyright (C) 1993-2013 Otfried Cheong Ipe is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. As a special exception, you have permission to link Ipe with the CGAL library and distribute executables, as long as you follow the requirements of the Gnu General Public License in regard to all of the software in the executable aside from CGAL. Ipe 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 General Public License for more details. You should have received a copy of the GNU General Public License along with Ipe; if not, you can find it at "http://www.gnu.org/copyleft/gpl.html", or write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ #ifndef IPESHAPE_H #define IPESHAPE_H #include "ipegeo.h" // -------------------------------------------------------------------- namespace ipe { class Painter; class Ellipse; class ClosedSpline; class Curve; class CurveSegment { public: enum Type { EArc, ESegment, EQuad, EBezier, ESpline }; //! Type of segment. inline Type type() const { return iType; } //! Number of control points. inline int countCP() const { return iNumCP; } //! Return control point. inline Vector cp(int i) const { return iCP[i]; } //! Return last control point. inline Vector last() const { return iCP[iNumCP - 1]; } //! Matrix (if Type() == EArc). inline Matrix matrix() const { return *iM; } Bezier bezier() const; Arc arc() const; void beziers(std::vector &bez) const; void draw(Painter &painter) const; void addToBBox(Rect &box, const Matrix &m, bool cp) const; double distance(const Vector &v, const Matrix &m, double bound) const; void snapVtx(const Vector &mouse, const Matrix &m, Vector &pos, double &bound) const; void snapBnd(const Vector &mouse, const Matrix &m, Vector &pos, double &bound) const; private: CurveSegment(Type type, int num, const Vector *cp, const Matrix *m = 0); private: Type iType; const Vector *iCP; int iNumCP; const Matrix *iM; friend class Curve; }; class SubPath { public: //! The subpath types. enum Type { ECurve, EEllipse, EClosedSpline }; virtual ~SubPath() = 0; //! Return type of this subpath. virtual Type type() const = 0; virtual bool closed() const; virtual const Ellipse *asEllipse() const; // virtual Ellipse *asEllipse(); virtual const ClosedSpline *asClosedSpline() const; // virtual ClosedSpline *asClosedSpline(); virtual const Curve *asCurve() const; // virtual Curve *asCurve(); //! Save subpath to XML stream. virtual void save(Stream &stream) const = 0; //! Draw subpath (does not call drawPath()). virtual void draw(Painter &painter) const = 0; //! Add subpath to box. virtual void addToBBox(Rect &box, const Matrix &m, bool cp) const = 0; //! Return distance from \a v to subpath transformed by \a m. virtual double distance(const Vector &v, const Matrix &m, double bound) const = 0; //! Snap to vertex. virtual void snapVtx(const Vector &mouse, const Matrix &m, Vector &pos, double &bound) const = 0; //! Snap to boundary of subpath. virtual void snapBnd(const Vector &mouse, const Matrix &m, Vector &pos, double &bound) const = 0; }; class Ellipse : public SubPath { public: Ellipse(const Matrix &m); virtual Type type() const; virtual const Ellipse *asEllipse() const; //! Return matrix that transforms unit circle to the ellipse. inline Matrix matrix() const { return iM; } virtual void save(Stream &stream) const; virtual void draw(Painter &painter) const; virtual void addToBBox(Rect &box, const Matrix &m, bool cp) const; virtual double distance(const Vector &v, const Matrix &m, double bound) const; virtual void snapVtx(const Vector &mouse, const Matrix &m, Vector &pos, double &bound) const; virtual void snapBnd(const Vector &mouse, const Matrix &m, Vector &pos, double &bound) const; private: Matrix iM; }; class ClosedSpline : public SubPath { public: ClosedSpline(const std::vector &v); virtual Type type() const; virtual const ClosedSpline *asClosedSpline() const; void beziers(std::vector &bez) const; virtual void save(Stream &stream) const; virtual void draw(Painter &painter) const; virtual void addToBBox(Rect &box, const Matrix &m, bool cp) const; virtual double distance(const Vector &v, const Matrix &m, double bound) const; virtual void snapVtx(const Vector &mouse, const Matrix &m, Vector &pos, double &bound) const; virtual void snapBnd(const Vector &mouse, const Matrix &m, Vector &pos, double &bound) const; public: std::vector iCP; // control points }; class Curve : public SubPath { public: Curve(); virtual Type type() const; inline virtual bool closed() const { return iClosed; } virtual const Curve *asCurve() const; virtual void save(Stream &stream) const; virtual void draw(Painter &painter) const; virtual void addToBBox(Rect &box, const Matrix &m, bool cp) const; virtual double distance(const Vector &v, const Matrix &m, double bound) const; virtual void snapVtx(const Vector &mouse, const Matrix &m, Vector &pos, double &bound) const; virtual void snapBnd(const Vector &mouse, const Matrix &m, Vector &pos, double &bound) const; /*! \brief Return number of segments. This does not include the closing segment for a closed path. */ int countSegments() const { return iSeg.size(); } CurveSegment segment(int i) const; CurveSegment closingSegment(Vector u[2]) const; void appendSegment(const Vector &v0, const Vector &v1); void appendArc(const Matrix &m, const Vector &v0, const Vector &v1); void appendQuad(const Vector &v0, const Vector &v1, const Vector &v2); void appendBezier(const Vector &v0, const Vector &v1, const Vector &v2, const Vector &v3); void appendSpline(const std::vector &v); void setClosed(bool closed); private: struct Seg { CurveSegment::Type iType; int iLastCP; int iMatrix; }; bool iClosed; std::vector iSeg; std::vector iCP; // control points std::vector iM; // for arcs }; class Shape { public: Shape(); explicit Shape(const Rect &rect); explicit Shape(const Segment &seg); explicit Shape(const Vector ¢er, double radius); explicit Shape(const Vector ¢er, double radius, double alpha0, double alpha1); ~Shape(); Shape(const Shape &rhs); Shape &operator=(const Shape &rhs); bool load(String data); void save(Stream &stream) const; void addToBBox(Rect &box, const Matrix &m, bool cp) const; double distance(const Vector &v, const Matrix &m, double bound) const; void snapVtx(const Vector &mouse, const Matrix &m, Vector &pos, double &bound) const; void snapBnd(const Vector &mouse, const Matrix &m, Vector &pos, double &bound) const; //! Return number of subpaths. inline int countSubPaths() const { return iImp->iSubPaths.size(); } //! Return subpath. inline const SubPath *subPath(int i) const { return iImp->iSubPaths[i]; } bool isSegment() const; void appendSubPath(SubPath *sp); void draw(Painter &painter) const; private: typedef std::vector SubPathSeq; struct Imp { ~Imp(); int iRefCount; SubPathSeq iSubPaths; }; Imp *iImp; }; } // namespace // -------------------------------------------------------------------- #endif ipe-7.1.4/src/include/ipepath.h0000644000175000017500000001473612120621776016206 0ustar otfriedotfried// -*- C++ -*- // -------------------------------------------------------------------- // The path object. // -------------------------------------------------------------------- /* This file is part of the extensible drawing editor Ipe. Copyright (C) 1993-2013 Otfried Cheong Ipe is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. As a special exception, you have permission to link Ipe with the CGAL library and distribute executables, as long as you follow the requirements of the Gnu General Public License in regard to all of the software in the executable aside from CGAL. Ipe 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 General Public License for more details. You should have received a copy of the GNU General Public License along with Ipe; if not, you can find it at "http://www.gnu.org/copyleft/gpl.html", or write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ #ifndef IPEPATH_H #define IPEPATH_H #include "ipeobject.h" #include "ipeshape.h" // -------------------------------------------------------------------- namespace ipe { class Path : public Object { public: explicit Path(const AllAttributes &attr, const Shape &shape, bool withArrows = false); static Path *create(const XmlAttributes &attr, String data); virtual Object *clone() const; virtual Path *asPath(); virtual Type type() const; void setPathMode(TPathMode pm); void setStroke(Attribute stroke); void setFill(Attribute fill); void setPen(Attribute pen); void setDashStyle(Attribute dash); void setLineCap(TLineCap s); void setLineJoin(TLineJoin s); void setFillRule(TFillRule s); void setOpacity(Attribute opaq); void setTiling(Attribute a); void setGradient(Attribute a); //! Return opacity of the opject. inline Attribute opacity() const { return iOpacity; } //! Return tiling pattern. inline Attribute tiling() const { return iTiling; } //! Return gradient fill. inline Attribute gradient() const { return iGradient; } inline TPathMode pathMode() const; inline Attribute stroke() const; inline Attribute fill() const; inline Attribute pen() const; inline Attribute dashStyle() const; inline TLineCap lineCap() const; inline TLineJoin lineJoin() const; inline TFillRule fillRule() const; virtual void saveAsXml(Stream &stream, String layer) const; virtual void draw(Painter &painter) const; virtual void drawSimple(Painter &painter) const; virtual void accept(Visitor &visitor) const; virtual void addToBBox(Rect &box, const Matrix &m, bool cp) const; virtual double distance(const Vector &v, const Matrix &m, double bound) const; virtual void snapVtx(const Vector &mouse, const Matrix &m, Vector &pos, double &bound) const; virtual void snapBnd(const Vector &mouse, const Matrix &m, Vector &pos, double &bound) const; virtual void checkStyle(const Cascade *sheet, AttributeSeq &seq) const; virtual bool setAttribute(Property prop, Attribute value, Attribute stroke, Attribute fill); virtual Attribute getAttribute(Property prop); inline bool arrow() const; inline bool rArrow() const; inline Attribute arrowShape() const; inline Attribute rArrowShape() const; inline Attribute arrowSize() const; inline Attribute rArrowSize() const; void setArrow(bool arrow, Attribute shape, Attribute size); void setRarrow(bool arrow, Attribute shape, Attribute size); static void drawArrow(Painter &painter, Vector pos, Angle alpha, Attribute shape, Attribute size, double radius); //! Return shape of the path object. const Shape &shape() const { return iShape; } void setShape(const Shape &shape); private: explicit Path(const XmlAttributes &attr); void init(const AllAttributes &attr, bool withArrows); void makeArrowData(); private: TPathMode iPathMode : 2; int iHasFArrow : 1; int iHasRArrow : 1; TLineJoin iLineJoin : 3; TLineCap iLineCap : 3; TFillRule iFillRule : 2; int iFArrowOk : 1; int iRArrowOk : 1; int iFArrowArc : 1; int iRArrowArc : 1; Attribute iStroke; Attribute iFill; Attribute iDashStyle; Attribute iPen; Attribute iOpacity; Attribute iTiling; Attribute iGradient; Attribute iFArrowShape; Attribute iRArrowShape; Attribute iFArrowSize; Attribute iRArrowSize; Vector iFArrowPos; Angle iFArrowDir; Vector iRArrowPos; Angle iRArrowDir; Shape iShape; }; // -------------------------------------------------------------------- //! Is the object stroked and filled? inline TPathMode Path::pathMode() const { return iPathMode; } //! Return stroke color. inline Attribute Path::stroke() const { return iStroke; } //! Return object fill color. inline Attribute Path::fill() const { return iFill; } //! Return object pen. inline Attribute Path::pen() const { return iPen; } //! Return object line style. inline Attribute Path::dashStyle() const { return iDashStyle; } //! Return line cap style. inline TLineCap Path::lineCap() const { return TLineCap(iLineCap); } //! Return line join style. inline TLineJoin Path::lineJoin() const { return TLineJoin(iLineJoin); } //! Return fill rule. inline TFillRule Path::fillRule() const { return TFillRule(iFillRule); } //! Does object have an arrow? inline bool Path::arrow() const { return iHasFArrow; } //! Does object have a reverse arrow? inline bool Path::rArrow() const { return iHasRArrow; } //! Return shape of arrow. inline Attribute Path::arrowShape() const { return iFArrowShape; } //! Return shape of reverse arrow. inline Attribute Path::rArrowShape() const { return iRArrowShape; } //! Return size of arrow. inline Attribute Path::arrowSize() const { return iFArrowSize; } //! Return size of reverse arrow. inline Attribute Path::rArrowSize() const { return iRArrowSize; } } // namespace // -------------------------------------------------------------------- #endif ipe-7.1.4/src/include/ipepdfwriter.h0000644000175000017500000001110512120621776017243 0ustar otfriedotfried// -*- C++ -*- // -------------------------------------------------------------------- // Creating PDF output // -------------------------------------------------------------------- /* This file is part of the extensible drawing editor Ipe. Copyright (C) 1993-2013 Otfried Cheong Ipe is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. As a special exception, you have permission to link Ipe with the CGAL library and distribute executables, as long as you follow the requirements of the Gnu General Public License in regard to all of the software in the executable aside from CGAL. Ipe 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 General Public License for more details. You should have received a copy of the GNU General Public License along with Ipe; if not, you can find it at "http://www.gnu.org/copyleft/gpl.html", or write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ #ifndef IPEPDFWRITER_H #define IPEPDFWRITER_H #include "ipebase.h" #include "ipepage.h" #include "ipedoc.h" #include "ipeimage.h" #include "ipefontpool.h" // -------------------------------------------------------------------- namespace ipe { class PdfPainter : public Painter { public: PdfPainter(const Cascade *style, Stream &stream); virtual ~PdfPainter() { } static void drawColor(Stream &stream, Color color, const char *gray, const char *rgb); protected: virtual void doPush(); virtual void doPop(); virtual void doNewPath(); virtual void doMoveTo(const Vector &v); virtual void doLineTo(const Vector &v); virtual void doCurveTo(const Vector &v1, const Vector &v2, const Vector &v3); virtual void doClosePath(); virtual void doDrawPath(TPathMode mode); virtual void doDrawBitmap(Bitmap bitmap); virtual void doDrawText(const Text *text); virtual void doAddClipPath(); virtual void doDrawSymbol(Attribute symbol); protected: void drawAttributes(); void drawOpacity(); protected: Stream &iStream; // iActiveState records the attribute settings that have been // recorded in the PDF output, to avoid repeating them // over and over again. std::list iActiveState; }; // -------------------------------------------------------------------- class PdfWriter { public: PdfWriter(TellStream &stream, const Document *doc, const FontPool *pool, bool markedView, int fromPage, int toPage, int compression); ~PdfWriter(); void createPages(); void createPageView(int page, int view); void createBookmarks(); void createXmlStream(String xmldata, bool preCompressed); void createTrailer(); private: int startObject(int objnum = -1); void createStream(const char *data, int size, bool preCompressed); void writeString(String text); void embedBitmap(Bitmap bitmap); void paintView(Stream &stream, int pno, int view); void embedBitmaps(const BitmapFinder &bm); void createResources(const BitmapFinder &bm); void embedFonts(const FontPool *pool); private: TellStream &iStream; const Document *iDoc; //! Show only last view of each page? bool iMarkedView; //! Obj id of XML stream. int iXmlStreamNum; //! Obj id of font resource dictionary. int iResourceNum; //! Obj id of outline dictionary. int iBookmarks; //! Compression level (0..9). int iCompressLevel; //! Obj id of font for page numbers. int iPageNumberFont; //! Obj id of GState with opacity definitions. int iExtGState; //! Obj id of dictionary with pattern definitions. int iPatternNum; // Export only those pages int iFromPage; int iToPage; std::vector iBitmaps; //! Next unused PDF object number. int iObjNum; //! Object numbers of gradients, indexed by attribute name std::map iGradients; //! Object numbers of symbols, indexed by attribute name std::map iSymbols; //! List of pages, expressed as Pdf object numbers. std::vector iPageObjectNumbers; //! List of file locations, in object number order (starting with 0). std::map iXref; }; } // namespace // -------------------------------------------------------------------- #endif ipe-7.1.4/src/include/ipefactory.h0000644000175000017500000000340512120621776016710 0ustar otfriedotfried// -*- C++ -*- // -------------------------------------------------------------------- // The Ipe object factory. // -------------------------------------------------------------------- /* This file is part of the extensible drawing editor Ipe. Copyright (C) 1993-2013 Otfried Cheong Ipe is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. As a special exception, you have permission to link Ipe with the CGAL library and distribute executables, as long as you follow the requirements of the Gnu General Public License in regard to all of the software in the executable aside from CGAL. Ipe 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 General Public License for more details. You should have received a copy of the GNU General Public License along with Ipe; if not, you can find it at "http://www.gnu.org/copyleft/gpl.html", or write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ #ifndef IPEFACTORY_H #define IPEFACTORY_H #include "ipebitmap.h" #include "ipeobject.h" // -------------------------------------------------------------------- namespace ipe { class ObjectFactory { public: static Object *createObject(String name, const XmlAttributes &attr, String data); static Object *createImage(String name, const XmlAttributes &attr, Bitmap bitmap); }; } // -------------------------------------------------------------------- #endif ipe-7.1.4/src/include/ipedoc.h0000644000175000017500000001260012120621776016003 0ustar otfriedotfried// -*- C++ -*- // -------------------------------------------------------------------- // The Ipe document. // -------------------------------------------------------------------- /* This file is part of the extensible drawing editor Ipe. Copyright (C) 1993-2013 Otfried Cheong Ipe is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. As a special exception, you have permission to link Ipe with the CGAL library and distribute executables, as long as you follow the requirements of the Gnu General Public License in regard to all of the software in the executable aside from CGAL. Ipe 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 General Public License for more details. You should have received a copy of the GNU General Public License along with Ipe; if not, you can find it at "http://www.gnu.org/copyleft/gpl.html", or write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ #ifndef IPEDOC_H #define IPEDOC_H #include "ipeobject.h" #include "ipepage.h" #include "ipeimage.h" #include "ipestyle.h" #include "ipefontpool.h" // -------------------------------------------------------------------- namespace ipe { class BitmapFinder; class Document { public: //! Properties of a document struct SProperties { SProperties(); String iTitle; String iAuthor; String iSubject; String iKeywords; String iPreamble; bool iFullScreen; bool iNumberPages; //! Date/time in PDF style "D:20010428191400" format. String iCreated; String iModified; //! Program that created this document (e.g. "Ipe 7.5"). String iCreator; }; //! There are several Ipe document save formats. enum TFormat { EXml, //!< Save as XML EPdf, //!< Save as PDF EEps, //!< Save as Encapsulated Postscript EIpe5, //!< Ancient Ipe format EUnknown //!< Unknown file format }; //! Options for saving Ipe documents (to PDF and Postscript) enum { ESaveNormal = 0, //!< Nothing special EExport = 1, //!< Don't include Ipe markup ENoZip = 2, //!< Do not compress streams EMarkedView = 4, //!< Create marked views only ENoColor = 8, //!< No color commands in EPS output }; //! Errors that can happen while loading documents enum LoadErrors { EVersionTooOld = -1, //!< The version of the file is too old. EVersionTooRecent = -2, //!< The file version is newer than this Ipelib. EFileOpenError = -3, //!< Error opening the file }; Document(); Document(const Document &rhs); ~Document(); static TFormat fileFormat(DataSource &source); static TFormat formatFromFilename(String fn); static Document *load(DataSource &source, TFormat format, int &reason); static Document *load(const char *fname, int &reason); static Document *loadWithErrorReport(const char *fname); bool save(TellStream &stream, TFormat format, uint flags) const; bool save(const char *fname, TFormat format, uint flags) const; bool exportPages(const char *fname, uint flags, int fromPage, int toPage) const; bool exportView(const char *fname, TFormat format, uint flags, int pno, int vno) const; void saveAsXml(Stream &stream, bool usePdfBitmaps = false) const; //! Return number of pages of document. int countPages() const { return int(iPages.size()); } int countTotalViews() const; //! Return page (const version). /*! The first page is no 0. */ const Page *page(int no) const { return iPages[no]; } //! Return page. /*! The first page is no 0. */ Page *page(int no) { return iPages[no]; } Page *set(int no, Page *page); void insert(int no, Page *page); void push_back(Page *page); Page *remove(int no); //! Return document properties. inline SProperties properties() const { return iProperties; } void setProperties(const SProperties &info); //! Return stylesheet cascade. Cascade *cascade() { return iCascade; } //! Return stylesheet cascade (const version). const Cascade *cascade() const { return iCascade; } Cascade *replaceCascade(Cascade *cascade); void setFontPool(FontPool *fontPool); //! Return the current FontPool. inline const FontPool *fontPool() const { return iFontPool; } bool hasTrueTypeFonts() const; bool hasTransparency() const; bool hasTilings() const; bool hasGradients() const; void findBitmaps(BitmapFinder &bm) const; bool checkStyle(AttributeSeq &seq) const; //! Error codes returned by RunLatex. enum { ErrNone, ErrNoText, ErrNoDir, ErrWritingSource, ErrOldPdfLatex, ErrRunLatex, ErrLatex, ErrLatexOutput, ErrNoIconv }; int runLatex(String &logFile); int runLatex(); private: // disable assignment Document &operator=(const Document &rhs); private: std::vector iPages; Cascade *iCascade; SProperties iProperties; FontPool *iFontPool; }; } // namespace // -------------------------------------------------------------------- #endif ipe-7.1.4/src/include/ipepage.h0000644000175000017500000001570212120621776016160 0ustar otfriedotfried// -*- C++ -*- // -------------------------------------------------------------------- // A page of a document. // -------------------------------------------------------------------- /* This file is part of the extensible drawing editor Ipe. Copyright (C) 1993-2013 Otfried Cheong Ipe is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. As a special exception, you have permission to link Ipe with the CGAL library and distribute executables, as long as you follow the requirements of the Gnu General Public License in regard to all of the software in the executable aside from CGAL. Ipe 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 General Public License for more details. You should have received a copy of the GNU General Public License along with Ipe; if not, you can find it at "http://www.gnu.org/copyleft/gpl.html", or write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ #ifndef IPEPAGE_H #define IPEPAGE_H #include "ipetext.h" // -------------------------------------------------------------------- namespace ipe { class StyleSheet; // -------------------------------------------------------------------- class Page { public: explicit Page(); static Page *basic(); void saveAsXml(Stream &stream) const; void saveAsIpePage(Stream &stream) const; void saveSelection(Stream &stream) const; //! Return number of layers. inline int countLayers() const { return iLayers.size(); } //! Return name of layer \a index. inline String layer(int index) const { return iLayers[index].iName; } //! Is layer \a i locked? inline bool isLocked(int i) const { return !!(iLayers[i].iFlags & ELocked); } //! Does layer \a i have active snapping? inline bool hasSnapping(int i) const { return !(iLayers[i].iFlags & ENoSnapping); } void setLocked(int i, bool flag); void setSnapping(int i, bool flag); void moveLayer(int index, int newIndex); int findLayer(String name) const; void addLayer(String name); void addLayer(); void removeLayer(String name); void renameLayer(String oldName, String newName); //! Return number of views. inline int countViews() const { return iViews.size(); } int countMarkedViews() const; //! Return effect of view. inline Attribute effect(int index) const { return iViews[index].iEffect; } void setEffect(int index, Attribute sym); //! Return active layer of view. inline String active(int index) const { return iViews[index].iActive; } //! Set active layer of view. void setActive(int index, String name); //! Return if view is marked. bool markedView(int index) const { return iViews[index].iMarked; } //! Set if view is marked. void setMarkedView(int index, bool marked); void insertView(int i, String active); void removeView(int i); void clearViews(); //! Is \a layer visible in \a view? inline bool visible(int view, int layer) const { return iLayers[layer].iVisible[view]; } //! Is object at index \a objno visible in \a view? inline bool objectVisible(int view, int objno) const { return iLayers[layerOf(objno)].iVisible[view]; } void setVisible(int view, String layer, bool vis); Rect textBox(const Cascade *sheet) const; //! Return title of this page. String title() const; void setTitle(String title); String section(int level) const; void setSection(int level, bool useTitle, String name); //! Does this section title reflect the page title? bool sectionUsesTitle(int level) const { return iUseTitle[level]; } const Text *titleText() const; void applyTitleStyle(const Cascade *sheet); //! Return if page is marked for printing. bool marked() const { return iMarked; } void setMarked(bool marked); //! Return notes for this page. String notes() const { return iNotes; } void setNotes(String notes); //! Return number of objects on the page. inline int count() const { return int(iObjects.size()); } //! Return object at index \a i. inline Object *object(int i) { return iObjects[i].iObject; } //! Return object at index \a i (const version). inline const Object *object(int i) const { return iObjects[i].iObject; } //! Return selection status of object at index \a i. inline TSelect select(int i) const { return iObjects[i].iSelect; } //! Return layer of object at index \a i. inline int layerOf(int i) const { return iObjects[i].iLayer; } //! Set selection status of object at index \a i. inline void setSelect(int i, TSelect sel) { iObjects[i].iSelect = sel; } //! Set layer of object at index \a i. inline void setLayerOf(int i, int layer) { iObjects[i].iLayer = layer; } Rect pageBBox(const Cascade *sheet) const; Rect viewBBox(const Cascade *sheet, int view) const; Rect bbox(int i) const; void transform(int i, const Matrix &m); double distance(int i, const Vector &v, double bound) const; void snapVtx(int i, const Vector &mouse, Vector &pos, double &bound) const; void snapBnd(int i, const Vector &mouse, Vector &pos, double &bound) const; void invalidateBBox(int i) const; void insert(int i, TSelect sel, int layer, Object *obj); void append(TSelect sel, int layer, Object *obj); void remove(int i); void replace(int i, Object *obj); bool setAttribute(int i, Property prop, Attribute value, Attribute stroke, Attribute fill); int primarySelection() const; bool hasSelection() const; void deselectAll(); void ensurePrimarySelection(); private: enum { ELocked = 0x01, ENoSnapping = 0x02 }; struct SLayer { public: SLayer(String name); public: String iName; int iFlags; // Invariant: iVisible.size() == iViews.size() std::vector iVisible; }; typedef std::vector LayerSeq; struct SView { public: SView() { iEffect = Attribute::NORMAL(); } public: Attribute iEffect; String iActive; bool iMarked; }; typedef std::vector ViewSeq; struct SObject { SObject(); SObject(const SObject &rhs); ~SObject(); SObject &operator=(const SObject &rhs); TSelect iSelect; int iLayer; mutable Rect iBBox; Object *iObject; }; typedef std::vector ObjSeq; LayerSeq iLayers; ViewSeq iViews; String iTitle; Text iTitleObject; bool iUseTitle[2]; String iSection[2]; ObjSeq iObjects; String iNotes; bool iMarked; }; } // namespace // -------------------------------------------------------------------- #endif ipe-7.1.4/src/include/ipefontpool.h0000644000175000017500000000517312120621776017105 0ustar otfriedotfried// -*- C++ -*- // -------------------------------------------------------------------- // The pool of embedded fonts. // -------------------------------------------------------------------- /* This file is part of the extensible drawing editor Ipe. Copyright (C) 1993-2013 Otfried Cheong Ipe is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. As a special exception, you have permission to link Ipe with the CGAL library and distribute executables, as long as you follow the requirements of the Gnu General Public License in regard to all of the software in the executable aside from CGAL. Ipe 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 General Public License for more details. You should have received a copy of the GNU General Public License along with Ipe; if not, you can find it at "http://www.gnu.org/copyleft/gpl.html", or write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ #ifndef IPEFONTPOOL_H #define IPEFONTPOOL_H #include "ipebase.h" #include "ipegeo.h" // -------------------------------------------------------------------- namespace ipe { //! A text font. struct Font { //! Ipe supports two types of fonts. enum TType { EType1, ETrueType }; //! The font type. TType iType; //! The name of this font (e.g. "Times-Roman"). String iName; //! The font id in the Pdflatex output: /Fxx int iLatexNumber; //! The font dictionary in the PDF file. String iFontDict; //! The font descriptor in the PDF file. String iFontDescriptor; //! The stream dictionary for the font stream in the PDF file. String iStreamDict; //! The values of LengthX in the font stream in the PDF file. int iLength1, iLength2, iLength3; //! The stream data for the font stream in the PDF file. Buffer iStreamData; //! Is there an explicit encoding for this font? bool iHasEncoding; //! The encoding of this font. String iEncoding[0x100]; //! Is this one of the 14 standard fonts? bool iStandardFont; //! The width of each character in font units. int iWidth[0x100]; }; //! A list of fonts used by a Document. \relates Font typedef std::vector FontPool; } // namespace // -------------------------------------------------------------------- #endif ipe-7.1.4/src/include/ipegeo.h0000644000175000017500000004340612120621776016020 0ustar otfriedotfried// -*- C++ -*- // -------------------------------------------------------------------- // Geometric primitives // -------------------------------------------------------------------- /* This file is part of the extensible drawing editor Ipe. Copyright (C) 1993-2013 Otfried Cheong Ipe is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. As a special exception, you have permission to link Ipe with the CGAL library and distribute executables, as long as you follow the requirements of the Gnu General Public License in regard to all of the software in the executable aside from CGAL. Ipe 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 General Public License for more details. You should have received a copy of the GNU General Public License along with Ipe; if not, you can find it at "http://www.gnu.org/copyleft/gpl.html", or write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ #ifndef IPEGEO_H #define IPEGEO_H #include "ipebase.h" #include // -------------------------------------------------------------------- #define IpePi 3.1415926535897932385 #define IpeTwoPi 6.2831853071795862 #define IpeHalfPi 1.5707963267948966 namespace ipe { /*! \ingroup geo Maximum of two values. */ template inline T max(const T &lhs, const T &rhs) { return (lhs > rhs) ? lhs : rhs; } /*! \ingroup geo Minimum of two values. */ template inline T min(const T &lhs, const T &rhs) { return (lhs < rhs) ? lhs : rhs; } /*! \ingroup geo Absolute value. */ inline double abs(double val) { return (val > 0) ? val : -val; } // -------------------------------------------------------------------- class Angle { public: //! Construct uninitialized angle. inline explicit Angle() { /* nothing */ } //! Construct an angle (in radians). inline Angle(double alpha) : iAlpha(alpha) { } //! Construct an angle in degrees. inline static Angle Degrees(double alpha) { return Angle(alpha * IpePi / 180.0); } //! Return value (in radians). inline operator double() const { return iAlpha; } double degrees() const; Angle normalize(double lowlimit); bool liesBetween(Angle small, Angle large) const; private: double iAlpha; }; // -------------------------------------------------------------------- class Vector { public: //! Uninitialized vector. Vector() { /* no initialization */ } explicit Vector(Angle alpha); //! Construct a vector. explicit Vector(double x0, double y0) : x(x0), y(y0) { } //! Return square of Euclidean length inline double sqLen() const; double len() const; Angle angle() const; Vector normalized() const; Vector orthogonal() const; double factorize(Vector &unit) const; bool snap(const Vector &mouse, Vector &pos, double &bound) const; inline bool operator==(const Vector &rhs) const; inline bool operator!=(const Vector &rhs) const; inline void operator+=(const Vector &rhs); inline void operator-=(const Vector &rhs); inline void operator*=(double rhs); inline Vector operator+(const Vector &rhs) const; inline Vector operator-(const Vector &rhs) const; inline Vector operator*(double rhs) const; inline Vector operator-() const; static Vector ZERO; public: double x; //!< Coordinates are public. double y; //!< Coordinates are public. }; /*! \relates Vector */ Stream &operator<<(Stream &stream, const Vector &rhs); // -------------------------------------------------------------------- class Rect { public: //! Create empty rectangle. explicit Rect() : iMin(1,0), iMax(-1,0) { } //! Create rectangle containing just the point \a c. explicit Rect(const Vector &c) : iMin(c), iMax(c) { } explicit Rect(const Vector &c1, const Vector &c2); //! Make rectangle empty. void clear() { iMin.x = 1.0; iMax.x = -1.0; iMin.y = iMax.y = 0; } //! True if rectangle is empty. int isEmpty() const { return iMin.x > iMax.x; } //! Return left side. inline double left() const { return iMin.x; } //! Return right side. inline double right() const { return iMax.x; } //! Return bottom side. inline double bottom() const { return iMin.y; } //! Return top side. inline double top() const { return iMax.y; } //! Return top right corner. inline Vector topRight() const { return iMax; } //! Return bottom left corner. inline Vector bottomLeft() const { return iMin; } //! Return top left corner. inline Vector topLeft() const { return Vector(iMin.x, iMax.y); } //! Return bottom right corner. inline Vector bottomRight() const { return Vector(iMax.x, iMin.y); } //! Return width. double width() const { return iMax.x - iMin.x; } //! Return height. double height() const { return iMax.y - iMin.y; } void addPoint(const Vector &rhs); void addRect(const Rect &rhs); void clipTo(const Rect &rhs); bool contains(const Vector &rhs) const; bool contains(const Rect &rhs) const; bool certainClearance(const Vector &v, double bound) const; bool intersects(const Rect &rhs) const; private: Vector iMin; //!< Lower-left corner. Vector iMax; //!< Top-right corner. }; /*! \relates Rect */ Stream &operator<<(Stream &stream, const Rect &rhs); // -------------------------------------------------------------------- class Line { public: //! Create default line (x-axis). explicit Line() : iP(0.0, 0.0), iDir(1.0, 0.0) { } explicit Line(const Vector &p, const Vector &dir); static Line through(const Vector &p, const Vector &q); double side(const Vector &p) const; inline Vector normal() const; double distance(const Vector &v) const; bool intersects(const Line &line, Vector &pt); Vector project(const Vector &v) const; inline Vector dir() const; public: //! Point on the line. Vector iP; private: Vector iDir; // unit vector }; // -------------------------------------------------------------------- class Segment { public: //! Create uninitialized segment Segment() { /* nothing */ } explicit Segment(const Vector &p, const Vector &q) : iP(p), iQ(q) { } inline Line line() const; double distance(const Vector &v, double bound) const; double distance(const Vector &v) const; bool project(const Vector &v, Vector &projection) const; bool intersects(const Segment &seg, Vector &pt) const; bool intersects(const Line &l, Vector &pt) const; bool snap(const Vector &mouse, Vector &pos, double &bound) const; public: //! First endpoint. Vector iP; //! Second endpoint. Vector iQ; }; // -------------------------------------------------------------------- class Bezier { public: //! Default constructor, uninitialized curve. inline Bezier() { /* nothing */ } inline Bezier(const Vector &p0, const Vector &p1, const Vector &p2, const Vector &p3); Vector point(double t) const; Vector tangent(double t) const; double distance(const Vector &v, double bound); bool straight(double precision) const; void subdivide(Bezier &l, Bezier &r) const; void approximate(double precision, std::vector &result) const; Rect bbox() const; bool snap(const Vector &v, double &t, Vector &pos, double &bound) const; static Bezier quadBezier(const Vector &p0, const Vector &p1, const Vector &p2); static void spline(int n, const Vector *v, std::vector &result); static void closedSpline(int n, const Vector *v, std::vector &result); void intersect(const Line &l, std::vector &result) const; void intersect(const Segment &l, std::vector &result) const; void intersect(const Bezier &b, std::vector &result) const; public: Vector iV[4]; }; // -------------------------------------------------------------------- class Linear { public: Linear(); explicit Linear(Angle angle); inline explicit Linear(double m11, double m21, double m12, double m22); explicit Linear(String str); Linear inverse() const; inline bool isIdentity() const; inline Vector operator*(const Vector &rhs) const; inline bool operator==(const Linear &rhs) const; inline double determinant() const; public: double a[4]; }; /*! \relates Linear */ Stream &operator<<(Stream &stream, const Linear &rhs); // -------------------------------------------------------------------- class Matrix { public: Matrix(); inline Matrix(const Linear &linear); inline explicit Matrix(const Linear &linear, const Vector &t); inline explicit Matrix(double m11, double m21, double m12, double m22, double t1, double t2); inline explicit Matrix(const Vector &v); explicit Matrix(String str); Matrix inverse() const; inline Vector operator*(const Vector &rhs) const; inline Bezier operator*(const Bezier &rhs) const; inline Vector translation() const; inline Linear linear() const; inline bool isIdentity() const; inline bool operator==(const Matrix &rhs) const; public: double a[6]; }; /*! \relates Matrix */ Stream &operator<<(Stream &stream, const Matrix &rhs); // -------------------------------------------------------------------- class Arc { public: inline Arc(); inline Arc(const Matrix &m, Angle alpha, Angle beta); inline Arc(const Matrix &m); Arc(const Matrix &m0, const Vector &begp, const Vector &endp); inline bool isEllipse() const; double distance(const Vector &v, double bound) const; double distance(const Vector &v, double bound, Vector &pos, Angle &angle) const; Rect bbox() const; inline Vector beginp() const; inline Vector endp() const; void intersect(const Line &l, std::vector &result) const; void intersect(const Segment &s, std::vector &result) const; void intersect(const Arc &a, std::vector &result) const; void intersect(const Bezier &b, std::vector &result) const; private: void subdivide(Arc &l, Arc &r) const; bool straight(const double precision) const; public: Matrix iM; Angle iAlpha; Angle iBeta; }; // -------------------------------------------------------------------- //! Return square of vector's length. inline double Vector::sqLen() const { return (x * x + y * y); } //! Equality. inline bool Vector::operator==(const Vector &rhs) const { return x == rhs.x && y == rhs.y; } //! Inequality. inline bool Vector::operator!=(const Vector &rhs) const { return x != rhs.x || y != rhs.y; } //! Vector-addition. inline void Vector::operator+=(const Vector &rhs) { x += rhs.x; y += rhs.y; } //! Vector-subtraction. inline void Vector::operator-=(const Vector &rhs) { x -= rhs.x; y -= rhs.y; } //! Multiply vector by scalar. inline void Vector::operator*=(double rhs) { x *= rhs; y *= rhs; } //! Vector-addition. inline Vector Vector::operator+(const Vector &rhs) const { Vector result = *this; result += rhs; return result; } //! Vector-subtraction. inline Vector Vector::operator-(const Vector &rhs) const { Vector result = *this; result -= rhs; return result; } //! Vector * scalar. inline Vector Vector::operator*(double rhs) const { Vector result = *this; result *= rhs; return result; } //! Scalar * vector. \relates Vector inline Vector operator*(double lhs, const Vector &rhs) { return Vector(lhs * rhs.x, lhs * rhs.y); } //! Dotproduct of two vectors. \relates Vector inline double dot(const Vector &lhs, const Vector &rhs) { return lhs.x * rhs.x + lhs.y * rhs.y; } //! Return a normal vector pointing to the left of the directed line. inline Vector Line::normal() const { return Vector(-iDir.y, iDir.x); } //! Return direction of line. inline Vector Line::dir() const { return iDir; } //! Return directed line supporting the segment. inline Line Segment::line() const { return Line(iP, (iQ - iP).normalized()); } //! Unary minus for Vector. inline Vector Vector::operator-() const { return -1 * *this; } //! Constructor with four control points. inline Bezier::Bezier(const Vector &p0, const Vector &p1, const Vector &p2, const Vector &p3) { iV[0] = p0; iV[1] = p1; iV[2] = p2; iV[3] = p3; } //! Transform Bezier spline. \relates Matrix inline Bezier Matrix::operator*(const Bezier &rhs) const { return Bezier(*this * rhs.iV[0], *this * rhs.iV[1], *this * rhs.iV[2], *this * rhs.iV[3]); }; // -------------------------------------------------------------------- //! Construct unit circle. inline Arc::Arc() : iAlpha(0.0), iBeta(IpeTwoPi) { // nothing } //! Construct with given parameters. inline Arc::Arc(const Matrix &m, Angle alpha, Angle beta) : iM(m), iAlpha(alpha), iBeta(beta) { // nothing } //! Construct an ellipse inline Arc::Arc(const Matrix &m) : iM(m), iAlpha(0.0), iBeta(IpeTwoPi) { // nothing } //! Is this an entire ellipse? inline bool Arc::isEllipse() const { return iAlpha == 0.0 && iBeta == IpeTwoPi; } //! Return begin point of arc. inline Vector Arc::beginp() const { return iM * Vector(Angle(iAlpha)); } //! Return end point of arc. inline Vector Arc::endp() const { return iM * Vector(Angle(iBeta)); } // -------------------------------------------------------------------- //! Create identity matrix. inline Linear::Linear() { a[0] = a[3] = 1.0; a[1] = a[2] = 0.0; } //! Create linear matrix with given coefficients. inline Linear::Linear(double m11, double m21, double m12, double m22) { a[0] = m11; a[1] = m21; a[2] = m12; a[3] = m22; } //! Linear matrix times vector. \relates Linear inline Vector Linear::operator*(const Vector &rhs) const { return Vector(a[0] * rhs.x + a[2] * rhs.y, a[1] * rhs.x + a[3] * rhs.y); }; //! Is this the identity matrix? inline bool Linear::isIdentity() const { return (a[0] == 1.0 && a[1] == 0.0 && a[2] == 0.0 && a[3] == 1.0); } //! Linear matrix multiplication. \relates Linear inline Linear operator*(const Linear &lhs, const Linear &rhs) { Linear m; m.a[0] = lhs.a[0] * rhs.a[0] + lhs.a[2] * rhs.a[1]; m.a[1] = lhs.a[1] * rhs.a[0] + lhs.a[3] * rhs.a[1]; m.a[2] = lhs.a[0] * rhs.a[2] + lhs.a[2] * rhs.a[3]; m.a[3] = lhs.a[1] * rhs.a[2] + lhs.a[3] * rhs.a[3]; return m; } //! Check for equality of two linear matrices. inline bool Linear::operator==(const Linear &rhs) const { return (a[0] == rhs.a[0] && a[1] == rhs.a[1] && a[2] == rhs.a[2] && a[3] == rhs.a[3]); } //! Return determinant of a linear matrix. inline double Linear::determinant() const { return (a[0] * a[3] - a[1] * a[2]); } // -------------------------------------------------------------------- //! Create matrix with given coefficients. inline Matrix::Matrix(double m11, double m21, double m12, double m22, double t1, double t2) { a[0] = m11; a[1] = m21; a[2] = m12; a[3] = m22; a[4] = t1; a[5] = t2; } //! Create linear matrix. inline Matrix::Matrix(const Linear &linear) { a[0] = linear.a[0]; a[1] = linear.a[1]; a[2] = linear.a[2]; a[3] = linear.a[3]; a[4] = a[5] = 0.0; } inline Matrix::Matrix(const Linear &linear, const Vector &t) { a[0] = linear.a[0]; a[1] = linear.a[1]; a[2] = linear.a[2]; a[3] = linear.a[3]; a[4] = t.x; a[5] = t.y; } //! Matrix times vector. \relates Matrix inline Vector Matrix::operator*(const Vector &rhs) const { return Vector(a[0] * rhs.x + a[2] * rhs.y + a[4], a[1] * rhs.x + a[3] * rhs.y + a[5]); }; //! Is this the identity matrix? inline bool Matrix::isIdentity() const { return (a[0] == 1.0 && a[1] == 0.0 && a[2] == 0.0 && a[3] == 1.0 && a[4] == 0.0 && a[5] == 0.0); } //! Create identity matrix. inline Matrix::Matrix() { a[0] = a[3] = 1.0; a[1] = a[2] = a[4] = a[5] = 0.0; } //! Matrix multiplication. \relates Matrix inline Matrix operator*(const Matrix &lhs, const Matrix &rhs) { Matrix m; m.a[0] = lhs.a[0] * rhs.a[0] + lhs.a[2] * rhs.a[1]; m.a[1] = lhs.a[1] * rhs.a[0] + lhs.a[3] * rhs.a[1]; m.a[2] = lhs.a[0] * rhs.a[2] + lhs.a[2] * rhs.a[3]; m.a[3] = lhs.a[1] * rhs.a[2] + lhs.a[3] * rhs.a[3]; m.a[4] = lhs.a[0] * rhs.a[4] + lhs.a[2] * rhs.a[5] + lhs.a[4]; m.a[5] = lhs.a[1] * rhs.a[4] + lhs.a[3] * rhs.a[5] + lhs.a[5]; return m; } //! Create translation matrix. inline Matrix::Matrix(const Vector &v) { a[0] = a[3] = 1.0; a[1] = a[2] = 0.0; a[4] = v.x; a[5] = v.y; } //! Return translation component. inline Vector Matrix::translation() const { return Vector(a[4], a[5]); } //! Check for equality of two matrices. inline bool Matrix::operator==(const Matrix &rhs) const { return (a[0] == rhs.a[0] && a[1] == rhs.a[1] && a[2] == rhs.a[2] && a[3] == rhs.a[3] && a[4] == rhs.a[4] && a[5] == rhs.a[5]); } //! Return linear transformation component of this affine transformation. inline Linear Matrix::linear() const { return Linear(a[0], a[1], a[2], a[3]); } //! Transform arc. \relates Matrix // must be here because it uses Matrix multiplication above inline Arc operator*(const Matrix &lhs, const Arc &rhs) { return Arc(lhs * rhs.iM, rhs.iAlpha, rhs.iBeta); } } // namespace // -------------------------------------------------------------------- #endif ipe-7.1.4/src/include/ipepdfparser.h0000644000175000017500000001377012120621776017235 0ustar otfriedotfried// -*- C++ -*- // -------------------------------------------------------------------- // PDF file parser // -------------------------------------------------------------------- /* This file is part of the extensible drawing editor Ipe. Copyright (C) 1993-2013 Otfried Cheong Ipe is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. As a special exception, you have permission to link Ipe with the CGAL library and distribute executables, as long as you follow the requirements of the Gnu General Public License in regard to all of the software in the executable aside from CGAL. Ipe 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 General Public License for more details. You should have received a copy of the GNU General Public License along with Ipe; if not, you can find it at "http://www.gnu.org/copyleft/gpl.html", or write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ #ifndef IPEPDFPARSER_H #define IPEPDFPARSER_H #include "ipebase.h" // -------------------------------------------------------------------- namespace ipe { class PdfNull; class PdfBool; class PdfNumber; class PdfString; class PdfName; class PdfRef; class PdfArray; class PdfDict; class PdfFile; class PdfObj { public: virtual ~PdfObj() = 0; virtual const PdfNull *null() const; virtual const PdfBool *boolean() const; virtual const PdfNumber *number() const; virtual const PdfString *string() const; virtual const PdfName *name() const; virtual const PdfRef *ref() const; virtual const PdfArray *array() const; virtual const PdfDict *dict() const; virtual void write(Stream &stream) const = 0; String repr() const; }; class PdfNull : public PdfObj { public: explicit PdfNull() { /* nothing */ } virtual const PdfNull *null() const; virtual void write(Stream &stream) const; }; class PdfBool : public PdfObj { public: explicit PdfBool(bool val) : iValue(val) { /* nothing */ } virtual const PdfBool *boolean() const; virtual void write(Stream &stream) const; inline bool value() const { return iValue; } private: bool iValue; }; class PdfNumber : public PdfObj { public: explicit PdfNumber(double val) : iValue(val) { /* nothing */ } virtual const PdfNumber *number() const; virtual void write(Stream &stream) const; inline double value() const { return iValue; } private: double iValue; }; class PdfString : public PdfObj { public: explicit PdfString(const String &val) : iValue(val) { /* nothing */ } virtual const PdfString *string() const; virtual void write(Stream &stream) const; inline String value() const { return iValue; } private: String iValue; }; class PdfName : public PdfObj { public: explicit PdfName(const String &val) : iValue(val) { /* nothing */ } virtual const PdfName *name() const; virtual void write(Stream &stream) const; inline String value() const { return iValue; } private: String iValue; }; class PdfRef : public PdfObj { public: explicit PdfRef(int val) : iValue(val) { /* nothing */ } virtual const PdfRef *ref() const; virtual void write(Stream &stream) const; inline int value() const { return iValue; } private: int iValue; }; class PdfArray : public PdfObj { public: explicit PdfArray() { /* nothing */ } ~PdfArray(); virtual const PdfArray *array() const; virtual void write(Stream &stream) const; void append(const PdfObj *); inline int count() const { return iObjects.size(); } const PdfObj *obj(int index, const PdfFile *file) const; private: std::vector iObjects; }; class PdfDict : public PdfObj { public: explicit PdfDict() { /* nothing */ } ~PdfDict(); virtual const PdfDict *dict() const; virtual void write(Stream &stream) const; void setStream(const Buffer &stream); void add(String key, const PdfObj *obj); const PdfObj *get(String key, const PdfFile *file) const; inline int count() const { return iItems.size(); } inline String key(int index) const { return iItems[index].iKey; } inline Buffer stream() const { return iStream; } bool deflated() const; // Buffer Inflate() const; private: struct Item { String iKey; const PdfObj *iVal; }; std::vector iItems; Buffer iStream; }; // -------------------------------------------------------------------- //! A PDF lexical token. struct PdfToken { //! The various types of tokens. enum TToken { EErr, EOp, EName, ENumber, EString, ETrue, EFalse, ENull, EArrayBg, EArrayEnd, EDictBg, EDictEnd }; //! The type of this token. TToken iType; //! The string representing this token. String iString; }; class PdfParser { public: PdfParser(DataSource &source); inline void getChar() { iCh = iSource.getChar(); ++iPos; } inline bool eos() const { return (iCh == EOF); } inline PdfToken token() const { return iTok; } void getToken(); PdfObj *getObject(); PdfObj *getObjectDef(); PdfDict *getTrailer(); void skipXRef(); private: void skipWhiteSpace(); PdfArray *makeArray(); PdfDict *makeDict(); private: DataSource &iSource; int iPos; int iCh; PdfToken iTok; }; class PdfFile { public: PdfFile(); ~PdfFile(); bool parse(DataSource &source); const PdfObj *object(int num) const; const PdfDict *catalog() const; const PdfDict *page() const; private: std::map iObjects; const PdfDict *iTrailer; }; } // namespace // -------------------------------------------------------------------- #endif ipe-7.1.4/src/include/ipelet.h0000644000175000017500000000623212120621776016026 0ustar otfriedotfried// -*- C++ -*- // -------------------------------------------------------------------- // Ipelets // -------------------------------------------------------------------- /* This file is part of the extensible drawing editor Ipe. Copyright (C) 1993-2013 Otfried Cheong Ipe is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. As a special exception, you have permission to link Ipe with the CGAL library and distribute executables, as long as you follow the requirements of the Gnu General Public License in regard to all of the software in the executable aside from CGAL. Ipe 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 General Public License for more details. You should have received a copy of the GNU General Public License along with Ipe; if not, you can find it at "http://www.gnu.org/copyleft/gpl.html", or write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ #ifndef IPELET_H #define IPELET_H #include "ipebase.h" #include "ipeattributes.h" #include "ipesnap.h" #ifdef __MINGW32__ #define IPELET_DECLARE extern "C" __declspec(dllexport) #else #define IPELET_DECLARE extern "C" #endif // -------------------------------------------------------------------- namespace ipe { class Page; class Document; class IpeletHelper { public: enum { EOkButton, EOkCancelButtons, EYesNoCancelButtons, EDiscardCancelButtons, ESaveDiscardCancelButtons }; virtual ~IpeletHelper() = 0; //! Show a message in the status bar. virtual void message(const char *msg) = 0; //! Pop up a modal message box. /*! The \a details can be null. Choose one of EOkButton, EOkCancelButtons, EYesNoCancelButtons, EDiscardCancelButtons, ESaveDiscardCancelButtons for \a buttons. Returns 1 for Ok or Yes, 0 for No, -1 for Cancel. */ virtual int messageBox(const char *text, const char *details, int buttons) = 0; /*! Pop up a modal dialog asking the user to enter a string. Returns true if the user didn't cancel the dialog. */ virtual bool getString(const char *prompt, String &str) = 0; }; //! Information provided to an ipelet when it is run. struct IpeletData { Page *iPage; const Document *iDoc; int iPageNo, iView, iLayer; AllAttributes iAttributes; Snap iSnap; }; // -------------------------------------------------------------------- class Ipelet { public: virtual ~Ipelet() = 0; //! Return the version of Ipelib the Ipelet was linked against. virtual int ipelibVersion() const = 0; //! Run a function from the Ipelet. /*! Return true if page was changed and undo registration is necessary. */ virtual bool run(int function, IpeletData *data, IpeletHelper *helper) = 0; }; } // namespace // -------------------------------------------------------------------- #endif ipe-7.1.4/src/include/ipeutils.h0000644000175000017500000001021612120621776016377 0ustar otfriedotfried// -*- C++ -*- // -------------------------------------------------------------------- // Various utility classes // -------------------------------------------------------------------- /* This file is part of the extensible drawing editor Ipe. Copyright (C) 1993-2013 Otfried Cheong Ipe is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. As a special exception, you have permission to link Ipe with the CGAL library and distribute executables, as long as you follow the requirements of the Gnu General Public License in regard to all of the software in the executable aside from CGAL. Ipe 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 General Public License for more details. You should have received a copy of the GNU General Public License along with Ipe; if not, you can find it at "http://www.gnu.org/copyleft/gpl.html", or write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ #ifndef IPEUTILS_H #define IPEUTILS_H #include "ipebitmap.h" #include "ipepainter.h" // -------------------------------------------------------------------- namespace ipe { class Page; class BitmapFinder : public Visitor { public: void scanPage(const Page *page); virtual void visitGroup(const Group *obj); virtual void visitImage(const Image *obj); public: std::vector iBitmaps; }; class BBoxPainter : public Painter { public: BBoxPainter(const Cascade *style); Rect bbox() const { return iBBox; } protected: virtual void doPush(); virtual void doPop(); virtual void doNewPath(); virtual void doMoveTo(const Vector &v); virtual void doLineTo(const Vector &v); virtual void doCurveTo(const Vector &v1, const Vector &v2, const Vector &v3); virtual void doDrawPath(TPathMode mode); virtual void doDrawBitmap(Bitmap bitmap); virtual void doDrawText(const Text *text); virtual void doAddClipPath(); private: Rect iBBox; Vector iV; Rect iPathBox; std::list iClipBox; }; class A85Stream : public Stream { public: A85Stream(Stream &stream); virtual void putChar(char ch); virtual void close(); private: Stream &iStream; uchar iCh[4]; int iN; int iCol; }; class Base64Stream : public Stream { public: Base64Stream(Stream &stream); virtual void putChar(char ch); virtual void close(); private: Stream &iStream; uchar iCh[3]; int iN; int iCol; }; class DeflateStream : public Stream { public: DeflateStream(Stream &stream, int level); virtual ~DeflateStream(); virtual void putChar(char ch); virtual void close(); static Buffer deflate(const char *data, int size, int &deflatedSize, int compressLevel); private: struct Private; Stream &iStream; Private *iPriv; int iN; Buffer iIn; Buffer iOut; }; class A85Source : public DataSource { public: A85Source(DataSource &source); //! Get one more character, or EOF. virtual int getChar(); private: DataSource &iSource; bool iEof; int iN; int iIndex; uchar iBuf[4]; }; class Base64Source : public DataSource { public: Base64Source(DataSource &source); //! Get one more character, or EOF. virtual int getChar(); private: DataSource &iSource; bool iEof; int iIndex; int iBufLen; uchar iBuf[3]; }; class InflateSource : public DataSource { public: InflateSource(DataSource &source); virtual ~InflateSource(); //! Get one more character, or EOF. virtual int getChar(); private: void fillBuffer(); private: struct Private; DataSource &iSource; Private *iPriv; char *iP; Buffer iIn; Buffer iOut; }; } // namespace // -------------------------------------------------------------------- #endif ipe-7.1.4/src/include/ipegroup.h0000644000175000017500000000706612120621776016404 0ustar otfriedotfried// -*- C++ -*- // -------------------------------------------------------------------- // The group object. // -------------------------------------------------------------------- /* This file is part of the extensible drawing editor Ipe. Copyright (C) 1993-2013 Otfried Cheong Ipe is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. As a special exception, you have permission to link Ipe with the CGAL library and distribute executables, as long as you follow the requirements of the Gnu General Public License in regard to all of the software in the executable aside from CGAL. Ipe 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 General Public License for more details. You should have received a copy of the GNU General Public License along with Ipe; if not, you can find it at "http://www.gnu.org/copyleft/gpl.html", or write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ #ifndef IPEGROUP_H #define IPEGROUP_H #include "ipeobject.h" #include "ipeshape.h" // -------------------------------------------------------------------- namespace ipe { class Shape; class Group : public Object { private: typedef std::vector List; public: typedef List::const_iterator const_iterator; explicit Group(); Group(const Group &rhs); virtual ~Group(); explicit Group(const XmlAttributes &attr); Group &operator=(const Group &rhs); virtual Object *clone() const; virtual Group *asGroup(); virtual Type type() const; virtual TPinned pinned() const; virtual void accept(Visitor &visitor) const; virtual void saveAsXml(Stream &stream, String layer) const; virtual void draw(Painter &painter) const; virtual void drawSimple(Painter &painter) const; virtual void addToBBox(Rect &box, const Matrix &m, bool cp) const; virtual double distance(const Vector &v, const Matrix &m, double bound) const; virtual void snapVtx(const Vector &mouse, const Matrix &m, Vector &pos, double &bound) const; virtual void snapBnd(const Vector &mouse, const Matrix &m, Vector &pos, double &bound) const; inline const Shape &clip() const { return iClip; } void setClip(const Shape &clip); //! Return number of component objects. inline int count() const { return iImp->iObjects.size(); } //! Return object at index \a i. inline const Object *object(int i) const { return iImp->iObjects[i]; } //! Return iterator for first object. inline const_iterator begin() const { return iImp->iObjects.begin(); } //! Return iterator for end of sequence. inline const_iterator end() const { return iImp->iObjects.end(); } void push_back(Object *); void saveComponentsAsXml(Stream &stream) const; virtual void checkStyle(const Cascade *sheet, AttributeSeq &seq) const; virtual bool setAttribute(Property prop, Attribute value, Attribute stroke, Attribute fill); private: void detach(); private: struct Imp { List iObjects; int iRefCount; TPinned iPinned; // is any of the objects in the list pinned? }; Imp *iImp; Shape iClip; }; } // namespace // -------------------------------------------------------------------- #endif ipe-7.1.4/src/include/ipelatex.h0000644000175000017500000000521012120621776016352 0ustar otfriedotfried// -*- C++ -*- // -------------------------------------------------------------------- // Latex source to PDF converter // -------------------------------------------------------------------- /* This file is part of the extensible drawing editor Ipe. Copyright (C) 1993-2013 Otfried Cheong Ipe is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. As a special exception, you have permission to link Ipe with the CGAL library and distribute executables, as long as you follow the requirements of the Gnu General Public License in regard to all of the software in the executable aside from CGAL. Ipe 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 General Public License for more details. You should have received a copy of the GNU General Public License along with Ipe; if not, you can find it at "http://www.gnu.org/copyleft/gpl.html", or write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ #ifndef PDFLATEX_P_H #define PDFLATEX_P_H #include "ipepage.h" #include "ipetext.h" #include "ipepdfparser.h" #include "ipefontpool.h" // -------------------------------------------------------------------- namespace ipe { class Cascade; class TextCollectingVisitor; class Latex { public: Latex(const Cascade *sheet); ~Latex(); int scanObject(const Object *obj); int scanPage(Page *page); int createLatexSource(Stream &stream, String preamble); bool readPdf(DataSource &source); bool updateTextObjects(); FontPool *takeFontPool(); private: bool getXForm(const PdfObj *xform); bool getEmbeddedFont(int fno, int objno); void warn(String msg); private: struct SText { const Text *iText; Attribute iSize; }; typedef std::list TextList; typedef std::list XFormList; const Cascade *iCascade; PdfFile iPdf; //! List of text objects scanned. Objects not owned. TextList iTextObjects; //! List of XForm objects read from PDF file. Objects owned! XFormList iXForms; //! The embedded fonts. Owned! FontPool *iFontPool; //! Maps /F to object number; std::map iFontObjects; friend class ipe::TextCollectingVisitor; }; } // namespace // -------------------------------------------------------------------- #endif ipe-7.1.4/src/include/ipereference.h0000644000175000017500000000721512120621776017202 0ustar otfriedotfried// -*- C++ -*- // -------------------------------------------------------------------- // The reference object // -------------------------------------------------------------------- /* This file is part of the extensible drawing editor Ipe. Copyright (C) 1993-2013 Otfried Cheong Ipe is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. As a special exception, you have permission to link Ipe with the CGAL library and distribute executables, as long as you follow the requirements of the Gnu General Public License in regard to all of the software in the executable aside from CGAL. Ipe 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 General Public License for more details. You should have received a copy of the GNU General Public License along with Ipe; if not, you can find it at "http://www.gnu.org/copyleft/gpl.html", or write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ #ifndef IPEREF_H #define IPEREF_H #include "ipeobject.h" // -------------------------------------------------------------------- namespace ipe { class Cascade; class Reference : public Object { public: enum { EHasStroke = 0x001, EHasFill = 0x002, EHasPen = 0x004, EHasSize = 0x008, EIsMark = 0x010, EIsArrow = 0x020 }; explicit Reference(const AllAttributes &attr, Attribute name, Vector pos); explicit Reference(const XmlAttributes &attr, String data); virtual Object *clone() const; virtual Reference *asReference(); virtual Type type() const; virtual void accept(Visitor &visitor) const; virtual void saveAsXml(Stream &stream, String layer) const; virtual void draw(Painter &painter) const; virtual void drawSimple(Painter &painter) const; virtual void addToBBox(Rect &box, const Matrix &m, bool cp) const; virtual double distance(const Vector &v, const Matrix &m, double bound) const; virtual void snapVtx(const Vector &mouse, const Matrix &m, Vector &pos, double &bound) const; virtual void snapBnd(const Vector &mouse, const Matrix &m, Vector &pos, double &bound) const; virtual void checkStyle(const Cascade *sheet, AttributeSeq &seq) const; void setName(Attribute name); //! Return symbolic name. inline Attribute name() const { return iName; } void setStroke(Attribute color); //! Return stroke color. inline Attribute stroke() const { return iStroke; } void setFill(Attribute color); //! Return fill color. inline Attribute fill() const { return iFill; } //! Return pen. inline Attribute pen() const { return iPen; } void setPen(Attribute pen); void setSize(Attribute size); //! Return symbol size. inline Attribute size() const { return iSize; } //! Return position of symbol on page. inline Vector position() const { return iPos; } virtual bool setAttribute(Property prop, Attribute value, Attribute stroke, Attribute fill); virtual Attribute getAttribute(Property prop); inline uint flags() const { return iFlags; } static uint flagsFromName(String name); private: Attribute iName; Vector iPos; Attribute iSize; Attribute iStroke; Attribute iFill; Attribute iPen; uint iFlags; }; } // namespace // -------------------------------------------------------------------- #endif ipe-7.1.4/src/include/ipeimage.h0000644000175000017500000000552512120621776016330 0ustar otfriedotfried// -*- C++ -*- // -------------------------------------------------------------------- // The image object // -------------------------------------------------------------------- /* This file is part of the extensible drawing editor Ipe. Copyright (C) 1993-2013 Otfried Cheong Ipe is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. As a special exception, you have permission to link Ipe with the CGAL library and distribute executables, as long as you follow the requirements of the Gnu General Public License in regard to all of the software in the executable aside from CGAL. Ipe 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 General Public License for more details. You should have received a copy of the GNU General Public License along with Ipe; if not, you can find it at "http://www.gnu.org/copyleft/gpl.html", or write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ #ifndef IPEIMAGE_H #define IPEIMAGE_H #include "ipebitmap.h" #include "ipeobject.h" // -------------------------------------------------------------------- namespace ipe { class Image : public Object { public: explicit Image(const Rect &rect, Bitmap bitmap); explicit Image(const XmlAttributes &attr, String data); explicit Image(const XmlAttributes &attr, Bitmap bitmap); virtual Object *clone() const; virtual Image *asImage(); virtual Type type() const; virtual void saveAsXml(Stream &stream, String layer) const; virtual void draw(Painter &painter) const; virtual void drawSimple(Painter &painter) const; virtual void accept(Visitor &visitor) const; virtual double distance(const Vector &v, const Matrix &m, double bound) const; virtual void addToBBox(Rect &box, const Matrix &m, bool) const; virtual void snapVtx(const Vector &mouse, const Matrix &m, Vector &pos, double &bound) const; inline Rect rect() const; inline Bitmap bitmap() const; private: void init(const XmlAttributes &attr); private: Rect iRect; Bitmap iBitmap; }; // -------------------------------------------------------------------- //! Return the rectangle occupied by the image on the paper. /*! The transformation matrix is applied to this, of course. */ inline Rect Image::rect() const { return iRect; } //! Return Bitmap of the image. inline Bitmap Image::bitmap() const { return iBitmap; } } // namespace // -------------------------------------------------------------------- #endif ipe-7.1.4/src/include/ipesnap.h0000644000175000017500000000525012120621776016202 0ustar otfriedotfried// -*- C++ -*- // -------------------------------------------------------------------- // Snapping. // -------------------------------------------------------------------- /* This file is part of the extensible drawing editor Ipe. Copyright (C) 1993-2013 Otfried Cheong Ipe is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. As a special exception, you have permission to link Ipe with the CGAL library and distribute executables, as long as you follow the requirements of the Gnu General Public License in regard to all of the software in the executable aside from CGAL. Ipe 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 General Public License for more details. You should have received a copy of the GNU General Public License along with Ipe; if not, you can find it at "http://www.gnu.org/copyleft/gpl.html", or write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ #ifndef IPESNAP_H #define IPESNAP_H #include "ipegeo.h" // -------------------------------------------------------------------- namespace ipe { class Page; class Snap { public: //! The different snap modes as bitmasks. enum TSnapModes { ESnapNone = 0, ESnapVtx = 1, ESnapBd = 2, ESnapInt = 4, ESnapGrid = 8, ESnapAngle = 0x10, ESnapAuto = 0x20 }; int iSnap; //!< Activated snapping modes (TSnapModes) bool iGridVisible; //!< Is the grid visible? int iGridSize; //!< Snap grid spacing. double iAngleSize; //!< Angle for angular snapping. int iSnapDistance; //!< Snap distance (in pixels). bool iWithAxes; //!< Show coordinate system? Vector iOrigin; //!< Origin of coordinate system Angle iDir; //!< Direction of x-axis bool intersectionSnap(Vector &pos, const Page *page, double snapDist) const; bool snapAngularIntersection(Vector &pos, const Line &l, const Page *page, double snapDist) const; bool simpleSnap(Vector &pos, const Page *page, double snapDist) const; bool snap(Vector &pos, const Page *page, double snapDist, Vector *autoOrg = 0) const; Line getLine(const Vector &mouse, const Vector &base) const; bool setEdge(const Vector &pos, const Page *page); }; } // namespace // -------------------------------------------------------------------- #endif ipe-7.1.4/src/include/ipepainter.h0000644000175000017500000001334312120621776016705 0ustar otfriedotfried// -*- C++ -*- // -------------------------------------------------------------------- // Painter abstraction // -------------------------------------------------------------------- /* This file is part of the extensible drawing editor Ipe. Copyright (C) 1993-2013 Otfried Cheong Ipe is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. As a special exception, you have permission to link Ipe with the CGAL library and distribute executables, as long as you follow the requirements of the Gnu General Public License in regard to all of the software in the executable aside from CGAL. Ipe 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 General Public License for more details. You should have received a copy of the GNU General Public License along with Ipe; if not, you can find it at "http://www.gnu.org/copyleft/gpl.html", or write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ #ifndef IPEPAINTER_H #define IPEPAINTER_H #include "ipeattributes.h" #include "ipestyle.h" #include "ipebitmap.h" // -------------------------------------------------------------------- namespace ipe { class Painter { public: Painter(const Cascade *style); virtual ~Painter(); void transform(const Matrix &m); void untransform(TTransformations trans); void translate(const Vector &v); void push(); void pop(); void pushMatrix(); void popMatrix(); void newPath(); void moveTo(const Vector &v); void lineTo(const Vector &v); void curveTo(const Vector &v1, const Vector &v2, const Vector &v3); inline void curveTo(const Bezier &bezier); void rect(const Rect &re); void drawEllipse(); void drawArc(const Arc &arc); void closePath(); void drawPath(TPathMode mode); void drawBitmap(Bitmap bitmap); void drawText(const Text *text); void drawSymbol(Attribute symbol); void addClipPath(); void setStroke(Attribute color); void setFill(Attribute color); void setPen(Attribute pen); void setDashStyle(Attribute dash); void setLineCap(TLineCap cap); void setLineJoin(TLineJoin join); void setFillRule(TFillRule rule); void setSymStroke(Attribute color); void setSymFill(Attribute color); void setSymPen(Attribute wid); void setOpacity(Attribute opaq); void setTiling(Attribute til); void setGradient(Attribute grad); //! Return style sheet cascade. inline const Cascade *cascade() const { return iCascade; } //! Return current stroke color. inline Color stroke() const { return iState.back().iStroke; } //! Return current fill color. inline Color fill() const { return iState.back().iFill; } //! Return current transformation matrix. inline const Matrix &matrix() const { return iMatrix.back(); } //! Return current pen. inline Fixed pen() const {return iState.back().iPen; } //! Return current dash style (always absolute attribute). inline String dashStyle() const {return iState.back().iDashStyle; } void dashStyle(std::vector &dashes, double &offset) const; //! Return current line cap. inline TLineCap lineCap() const {return iState.back().iLineCap; } //! Return current line join. inline TLineJoin lineJoin() const {return iState.back().iLineJoin; } //! Return current fill rule. inline TFillRule fillRule() const {return iState.back().iFillRule; } //! Return current symbol stroke color. inline Color symStroke() const { return iState.back().iSymStroke; } //! Return current symbol fill color. inline Color symFill() const { return iState.back().iSymFill; } //! Return current symbol pen. inline Fixed symPen() const { return iState.back().iSymPen; } //! Return current opacity. inline Fixed opacity() const { return iState.back().iOpacity; } //! Return current tiling. inline Attribute tiling() const { return iState.back().iTiling; } //! Return current gradient fill. inline Attribute gradient() const { return iState.back().iGradient; } protected: virtual void doPush(); virtual void doPop(); virtual void doNewPath(); virtual void doMoveTo(const Vector &v); virtual void doLineTo(const Vector &v); virtual void doCurveTo(const Vector &v1, const Vector &v2, const Vector &v3); virtual void doDrawArc(const Arc &arc); virtual void doClosePath(); virtual void doDrawPath(TPathMode mode); virtual void doDrawBitmap(Bitmap bitmap); virtual void doDrawText(const Text *text); virtual void doDrawSymbol(Attribute symbol); virtual void doAddClipPath(); void drawArcAsBezier(double alpha); protected: struct State { Color iStroke; Color iFill; Fixed iPen; String iDashStyle; TLineCap iLineCap; TLineJoin iLineJoin; TFillRule iFillRule; Color iSymStroke; Color iSymFill; Fixed iSymPen; Fixed iOpacity; Attribute iTiling; Attribute iGradient; }; std::list iState; std::list iMatrix; const Cascade *iCascade; int iInPath; }; // -------------------------------------------------------------------- //! Overloaded function. /*! Assumes current position is \c bezier.iV[0] */ inline void Painter::curveTo(const Bezier &bezier) { curveTo(bezier.iV[1], bezier.iV[2], bezier.iV[3]); } } // namespace // -------------------------------------------------------------------- #endif ipe-7.1.4/src/include/ipetext.h0000644000175000017500000001437612120621776016236 0ustar otfriedotfried// -*- C++ -*- // -------------------------------------------------------------------- // The text object. // -------------------------------------------------------------------- /* This file is part of the extensible drawing editor Ipe. Copyright (C) 1993-2013 Otfried Cheong Ipe is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. As a special exception, you have permission to link Ipe with the CGAL library and distribute executables, as long as you follow the requirements of the Gnu General Public License in regard to all of the software in the executable aside from CGAL. Ipe 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 General Public License for more details. You should have received a copy of the GNU General Public License along with Ipe; if not, you can find it at "http://www.gnu.org/copyleft/gpl.html", or write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ #ifndef IPETEXT_H #define IPETEXT_H #include "ipeobject.h" // -------------------------------------------------------------------- namespace ipe { class Text : public Object { public: enum TextType { ELabel = 1, EMinipage }; explicit Text(); explicit Text(const AllAttributes &attr, String data, const Vector &pos, TextType type, double width = 10.0); Text(const Text &rhs); ~Text(); explicit Text(const XmlAttributes &attr, String data); virtual Object *clone() const; virtual Text *asText(); virtual Type type() const; virtual void saveAsXml(Stream &stream, String layer) const; virtual void draw(Painter &painter) const; virtual void drawSimple(Painter &painter) const; virtual void accept(Visitor &visitor) const; virtual void addToBBox(Rect &box, const Matrix &m, bool) const; virtual double distance(const Vector &v, const Matrix &m, double bound) const; virtual void snapVtx(const Vector &mouse, const Matrix &m, Vector &pos, double &bound) const; virtual void checkStyle(const Cascade *sheet, AttributeSeq &seq) const; virtual bool setAttribute(Property prop, Attribute value, Attribute stroke, Attribute fill); virtual Attribute getAttribute(Property prop); private: void quadrilateral(const Matrix &m, Vector v[4]) const; public: Vector align() const; TextType textType() const; inline Vector position() const; inline String text() const; void setStroke(Attribute stroke); void setOpacity(Attribute opaq); inline Attribute stroke() const; inline Attribute size() const; inline Attribute style() const; //! Return opacity of the opject. inline Attribute opacity() const { return iOpacity; } inline bool isMinipage() const; void setTextType(TextType type); inline THorizontalAlignment horizontalAlignment() const; inline TVerticalAlignment verticalAlignment() const; void setHorizontalAlignment(THorizontalAlignment align); void setVerticalAlignment(TVerticalAlignment align); static TVerticalAlignment makeVAlign(String str, TVerticalAlignment def); static THorizontalAlignment makeHAlign(String str, THorizontalAlignment def); static void saveAlignment(Stream &stream, THorizontalAlignment h, TVerticalAlignment v); inline double width() const; inline double height() const; inline double depth() const; inline double totalHeight() const; void setSize(Attribute size); void setStyle(Attribute style); void setWidth(double width); void setText(String text); struct XForm { unsigned long int iRefCount; Buffer iStream; Rect iBBox; int iDepth; std::vector iFonts; double iStretch; }; bool isInternal() const { return iType == 0; } void setXForm(XForm *xform) const; inline const XForm *getXForm() const; private: Vector iPos; String iText; Attribute iStroke; Attribute iSize; Attribute iStyle; Attribute iOpacity; mutable double iWidth; mutable double iHeight; mutable double iDepth; TextType iType; THorizontalAlignment iHorizontalAlignment; TVerticalAlignment iVerticalAlignment; mutable XForm *iXForm; // reference counted }; // -------------------------------------------------------------------- //! Return text position. inline Vector Text::position() const { return iPos; } //! Return text source. inline String Text::text() const { return iText; } //! Return stroke color. inline Attribute Text::stroke() const { return iStroke; } //! Return font size. inline Attribute Text::size() const { return iSize; } //! Return Latex style of text object. inline Attribute Text::style() const { return iStyle; } //! Return width of text object. inline double Text::width() const { return iWidth; } //! Return height of text object (from baseline to top). inline double Text::height() const { return iHeight; } //! Return depth of text object. inline double Text::depth() const { return iDepth; } //! Return height + depth of text object. inline double Text::totalHeight() const { return iHeight + iDepth; } //! Return true if text object is formatted as a minipage. /*! Equivalent to type being EMinipage. */ inline bool Text::isMinipage() const { return (iType == EMinipage); } //! Return horizontal alignment of text object. inline THorizontalAlignment Text::horizontalAlignment() const { return iHorizontalAlignment; } //! Return vertical alignment of text object. inline TVerticalAlignment Text::verticalAlignment() const { return iVerticalAlignment; } //! Return the PDF representation of this text object. /*! If Pdflatex has not been run yet, returns 0. */ inline const Text::XForm *Text::getXForm() const { return iXForm; } } // namespace // -------------------------------------------------------------------- #endif ipe-7.1.4/src/include/ipebase.h0000644000175000017500000002506112120621776016155 0ustar otfriedotfried// -*- C++ -*- // -------------------------------------------------------------------- // Base header file --- must be included by all Ipe components. // -------------------------------------------------------------------- /* This file is part of the extensible drawing editor Ipe. Copyright (C) 1993-2013 Otfried Cheong Ipe is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. As a special exception, you have permission to link Ipe with the CGAL library and distribute executables, as long as you follow the requirements of the Gnu General Public License in regard to all of the software in the executable aside from CGAL. Ipe 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 General Public License for more details. You should have received a copy of the GNU General Public License along with Ipe; if not, you can find it at "http://www.gnu.org/copyleft/gpl.html", or write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ #ifndef IPEBASE_H #define IPEBASE_H #include #include #include #include #include #include // -------------------------------------------------------------------- typedef unsigned char uchar; #if defined(__MINGW32__) || defined(__APPLE__) typedef unsigned short ushort; typedef unsigned int uint; typedef unsigned long int ulong; #endif #undef assert #define assert(e) ((e) ? (void)0 : ipeAssertionFailed(__FILE__, __LINE__, #e)) extern void ipeAssertionFailed(const char *, int, const char *); // -------------------------------------------------------------------- extern void ipeDebug(const char *msg, ...); template class IpeAutoPtr { public: IpeAutoPtr(T *ptr) : iPtr(ptr) { /* nothing */ } ~IpeAutoPtr() { delete iPtr; } T *operator->() { return iPtr; } T &operator*() { return *iPtr; } T *ptr() { return iPtr; } T *take() { T *p = iPtr; iPtr = 0; return p; } private: T *iPtr; }; namespace ipe { //! Ipelib version. /*! \ingroup base */ const int IPELIB_VERSION = 70104; //! Oldest readable file format version. /*! \ingroup base */ const int OLDEST_FILE_FORMAT = 70000; //! Current file format version. /*! \ingroup base */ const int FILE_FORMAT = 70005; // -------------------------------------------------------------------- class Stream; class String { public: String(); String(const char *str); String(const String &rhs); String(const String &rhs, int index, int len); String &operator=(const String &rhs); ~String(); //! Return character at index i. inline char operator[](int i) const { return iImp->iData[i]; } //! Is the string empty? inline bool empty() const { return (size() == 0); } //! Is the string empty? inline bool isEmpty() const { return (size() == 0); } //! Return read-only pointer to the data. const char *data() const { return iImp->iData; } //! Return number of bytes in the string. inline int size() const { return iImp->iSize; } //! Operator syntax for append. inline void operator+=(const String &rhs) { append(rhs); } //! Operator syntax for append. void operator+=(char ch) { append(ch); } //! Create substring. inline String substr(int i, int len = -1) const { return String(*this, i, len); } //! Create substring at the left. inline String left(int i) const { return String(*this, 0, i); } String right(int i) const; //! Operator !=. inline bool operator!=(const String &rhs) const { return !(*this == rhs); } int find(char ch) const; int rfind(char ch) const; int find(const char *rhs) const; void erase(); void append(const String &rhs); void append(char ch); bool operator==(const String &rhs) const; bool operator<(const String &rhs) const; String operator+(const String &rhs) const; int unicode(int &index) const; const char *z() const; private: void detach(int n); private: struct Imp { int iRefCount; int iSize; int iCapacity; char *iData; }; Imp *iImp; }; // -------------------------------------------------------------------- class Fixed { public: explicit Fixed(int val) : iValue(val * 1000) { /* nothing */ } explicit Fixed() { /* nothing */ } inline static Fixed fromInternal(int val); static Fixed fromDouble(double val); inline int toInt() const { return iValue / 1000; } inline double toDouble() const { return iValue / 1000.0; } inline int internal() const { return iValue; } Fixed mult(int a, int b) const; inline bool operator==(const Fixed &rhs) const; inline bool operator!=(const Fixed &rhs) const; inline bool operator<(const Fixed &rhs) const; private: int iValue; friend Stream &operator<<(Stream &stream, const Fixed &f); }; // -------------------------------------------------------------------- class Lex { public: explicit Lex(String str); String token(); String nextToken(); int getInt(); int getHexByte(); Fixed getFixed(); unsigned long int getHexNumber(); double getDouble(); //! Extract next character (not skipping anything). inline char getChar() { return iString[iPos++]; } void skipWhitespace(); //! Operator syntax for getInt(). inline Lex &operator>>(int &i) { i = getInt(); return *this; } //! Operator syntax for getDouble(). inline Lex &operator>>(double &d) { d = getDouble(); return *this; } //! Operator syntax for getFixed(). inline Lex &operator>>(Fixed &d) { d = getFixed(); return *this; } //! Mark the current position. inline void mark() { iMark = iPos; } //! Reset reader to the marked position. inline void fromMark() { iPos = iMark; } //! Return true if at end of string (not even whitespace left). inline bool eos() const { return (iPos == iString.size()); } private: String iString; int iPos; int iMark; }; // -------------------------------------------------------------------- class Buffer { public: Buffer(); ~Buffer(); Buffer(const Buffer &rhs); Buffer &operator=(const Buffer &rhs); explicit Buffer(int size); explicit Buffer(const char *data, int size); //! Character access. inline char &operator[](int index) { return iImp->iData[index]; } //! Character access (const version). inline const char &operator[](int index) const { return iImp->iData[index]; } //! Return size of buffer; inline int size() const { return iImp->iSize; } //! Return pointer to buffer data. inline char *data() { return iImp->iData; } //! Return pointer to buffer data (const version). inline const char *data() const { return iImp->iData; } private: struct Imp { int iRefCount; char *iData; int iSize; }; Imp *iImp; }; // -------------------------------------------------------------------- class Stream { public: //! Virtual destructor. virtual ~Stream(); //! Output character. virtual void putChar(char ch) = 0; //! Close the stream. No more writing allowed! virtual void close(); //! Output string. virtual void putString(String s); //! Output C string. virtual void putCString(const char *s); //! Output raw character data. virtual void putRaw(const char *data, int size); //! Output character. inline Stream &operator<<(char ch) { putChar(ch); return *this; } //! Output string. inline Stream &operator<<(const String &s) { putString(s); return *this; } //! Output C string. inline Stream &operator<<(const char *s) { putCString(s); return *this; } Stream &operator<<(int i); Stream &operator<<(double d); void putHexByte(char b); void putXmlString(String s); }; /*! \class ipe::TellStream \ingroup base \brief Adds position feedback to IpeStream. */ class TellStream : public Stream { public: virtual long tell() const = 0; }; class StringStream : public TellStream { public: StringStream(String &string); virtual void putChar(char ch); virtual void putString(String s); virtual void putCString(const char *s); virtual void putRaw(const char *data, int size); virtual long tell() const; private: String &iString; }; class FileStream : public TellStream { public: FileStream(std::FILE *file); virtual void putChar(char ch); virtual void putString(String s); virtual void putCString(const char *s); virtual void putRaw(const char *data, int size); virtual long tell() const; private: std::FILE *iFile; }; // -------------------------------------------------------------------- class DataSource { public: virtual ~DataSource() = 0; //! Get one more character, or EOF. virtual int getChar() = 0; }; class FileSource : public DataSource { public: FileSource(std::FILE *file); virtual int getChar(); private: std::FILE *iFile; }; class BufferSource : public DataSource { public: BufferSource(const Buffer &buffer); virtual int getChar(); private: const Buffer &iBuffer; int iPos; }; // -------------------------------------------------------------------- class Platform { public: typedef void (*DebugHandler)(const char *); #ifdef WIN32 static String ipeDir(const char *suffix); #endif static int libVersion(); static void initLib(int version); static void setDebug(bool debug); static char pathSeparator(); static String currentDirectory(); static String latexDirectory(); static String fontmapFile(); static bool fileExists(String fname); static String readFile(String fname); static int runPdfLatex(String dir); }; // -------------------------------------------------------------------- inline bool Fixed::operator==(const Fixed &rhs) const { return iValue == rhs.iValue; } inline bool Fixed::operator!=(const Fixed &rhs) const { return iValue != rhs.iValue; } inline bool Fixed::operator<(const Fixed &rhs) const { return iValue < rhs.iValue; } inline Fixed Fixed::fromInternal(int val) { Fixed f; f.iValue = val; return f; } } // namespace // -------------------------------------------------------------------- #endif ipe-7.1.4/src/include/ipeobject.h0000644000175000017500000001233212120621776016506 0ustar otfriedotfried// -*- C++ -*- // -------------------------------------------------------------------- // The Ipe object type. // -------------------------------------------------------------------- /* This file is part of the extensible drawing editor Ipe. Copyright (C) 1993-2013 Otfried Cheong Ipe is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. As a special exception, you have permission to link Ipe with the CGAL library and distribute executables, as long as you follow the requirements of the Gnu General Public License in regard to all of the software in the executable aside from CGAL. Ipe 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 General Public License for more details. You should have received a copy of the GNU General Public License along with Ipe; if not, you can find it at "http://www.gnu.org/copyleft/gpl.html", or write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ #ifndef IPEOBJ_H #define IPEOBJ_H #include "ipeattributes.h" #include "ipexml.h" // -------------------------------------------------------------------- namespace ipe { class Visitor; class Painter; class Group; class Text; class Path; class Image; class Reference; class StyleSheet; class Cascade; // -------------------------------------------------------------------- class Object { public: enum Type { EGroup, EPath, EText, EImage, EReference }; virtual ~Object() = 0; //! Calls visitXXX method of the visitor. virtual void accept(Visitor &visitor) const = 0; //! Make a copy of this object (constant-time). virtual Object *clone() const = 0; virtual Group *asGroup(); virtual Text *asText(); virtual Path *asPath(); virtual Image *asImage(); virtual Reference *asReference(); virtual Type type() const = 0; virtual TPinned pinned() const; void setPinned(TPinned pin); //! Return allowed transformations of the object. inline TTransformations transformations() const { return iTransformations; } void setTransformations(TTransformations trans); void setMatrix(const Matrix &matrix); //! Return transformation matrix. inline const Matrix &matrix() const { return iMatrix; } virtual bool setAttribute(Property prop, Attribute value, Attribute stroke, Attribute fill); virtual Attribute getAttribute(Property prop); //! Save the object in XML format. virtual void saveAsXml(Stream &stream, String layer) const = 0; //! Draw the object. virtual void draw(Painter &painter) const = 0; //! Draw simple version for selecting and transforming. virtual void drawSimple(Painter &painter) const = 0; /*! Return distance of transformed object to point \a v. If larger than \a bound, can just return \a bound. */ virtual double distance(const Vector &v, const Matrix &m, double bound) const = 0; //! Extend \a box to include the object transformed by \a m. /*! For objects in a page, don't call this directly. The Page caches the bounding box of each object, so it is far more efficient to call Page::bbox. Control points that lie outside the visual object are included if \a cp is true. If called with an empty box and \a cp == \c false, the result of this function is a tight bounding box for the object, with a little leeway in case the boundary is determined by a spline (it has to be approximated to perform this operation). */ virtual void addToBBox(Rect &box, const Matrix &m, bool cp) const = 0; //! Compute possible vertex snapping position for transformed object. /*! Looks only for positions closer than \a bound. If successful, modify \a pos and \a bound. */ virtual void snapVtx(const Vector &mouse, const Matrix &m, Vector &pos, double &bound) const = 0; virtual void checkStyle(const Cascade *sheet, AttributeSeq &seq) const; virtual void snapBnd(const Vector &mouse, const Matrix &m, Vector &pos, double &bound) const; protected: explicit Object(); explicit Object(const AllAttributes &attr); Object(const Object &rhs); explicit Object(const XmlAttributes &attr); void saveAttributesAsXml(Stream &stream, String layer) const; static void checkSymbol(Kind kind, Attribute attr, const Cascade *sheet, AttributeSeq &seq); protected: Matrix iMatrix; TPinned iPinned : 8; TTransformations iTransformations : 8; }; // -------------------------------------------------------------------- class Visitor { public: virtual ~Visitor(); virtual void visitGroup(const Group *obj); virtual void visitPath(const Path *obj); virtual void visitText(const Text *obj); virtual void visitImage(const Image *obj); virtual void visitReference(const Reference *obj); }; } // namespace // -------------------------------------------------------------------- #endif ipe-7.1.4/src/include/ipebitmap.h0000644000175000017500000001332312120621776016515 0ustar otfriedotfried// -*- C++ -*- // -------------------------------------------------------------------- // Bitmaps // -------------------------------------------------------------------- /* This file is part of the extensible drawing editor Ipe. Copyright (C) 1993-2013 Otfried Cheong Ipe is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. As a special exception, you have permission to link Ipe with the CGAL library and distribute executables, as long as you follow the requirements of the Gnu General Public License in regard to all of the software in the executable aside from CGAL. Ipe 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 General Public License for more details. You should have received a copy of the GNU General Public License along with Ipe; if not, you can find it at "http://www.gnu.org/copyleft/gpl.html", or write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ #ifndef IPEBITMAP_H #define IPEBITMAP_H #include "ipebase.h" #include "ipexml.h" // -------------------------------------------------------------------- namespace ipe { class Bitmap { public: enum TFilter { EDirect, EFlateDecode, EDCTDecode }; enum TColorSpace { EDeviceRGB, EDeviceGray, EDeviceCMYK }; class MRenderData { public: virtual ~MRenderData(); }; Bitmap(); Bitmap(int width, int height, TColorSpace colorSpace, int bitsPerComponent, Buffer data, TFilter filter, bool deflate = false); Bitmap(const XmlAttributes &attr, String data); Bitmap(const XmlAttributes &attr, Buffer data); Bitmap(const Bitmap &rhs); ~Bitmap(); Bitmap &operator=(const Bitmap &rhs); void saveAsXml(Stream &stream, int id, int pdfObjNum = -1) const; inline bool isNull() const; bool equal(Bitmap rhs) const; inline TColorSpace colorSpace() const; inline TFilter filter() const; inline int components() const; inline int bitsPerComponent() const; inline int width() const; inline int height() const; int colorKey() const; void setColorKey(int key); inline const char *data() const; inline int size() const; inline int objNum() const; inline void setObjNum(int objNum) const; inline MRenderData *renderData() const; void setRenderData(MRenderData *data) const; Buffer pixelData() const; inline bool operator==(const Bitmap &rhs) const; inline bool operator!=(const Bitmap &rhs) const; inline bool operator<(const Bitmap &rhs) const; private: int init(const XmlAttributes &attr); void computeChecksum(); private: struct Imp { int iRefCount; TColorSpace iColorSpace; int iBitsPerComponent; int iWidth; int iHeight; int iComponents; int iColorKey; Buffer iData; TFilter iFilter; int iChecksum; mutable int iObjNum; // Object number (e.g. in PDF file) mutable MRenderData *iRender; // cached pixmap to render it fast }; Imp *iImp; }; // -------------------------------------------------------------------- //! Is this a null bitmap? inline bool Bitmap::isNull() const { return (iImp == 0); } //! Return the color space of the image. inline Bitmap::TColorSpace Bitmap::colorSpace() const { return iImp->iColorSpace; } //! Return number of components per pixel. inline int Bitmap::components() const { return iImp->iComponents; } //! Return the number of bits per component. inline int Bitmap::bitsPerComponent() const { return iImp->iBitsPerComponent; } //! Return width of pixel array. inline int Bitmap::width() const { return iImp->iWidth; } //! Return height of pixel array. inline int Bitmap::height() const { return iImp->iHeight; } //! Return the data filter of the image data. inline Bitmap::TFilter Bitmap::filter() const { return iImp->iFilter; } //! Return a pointer to the image data (in PDF arrangement). inline const char *Bitmap::data() const { return iImp->iData.data(); } //! Return size (number of bytes) of image data (in PDF arrangement). inline int Bitmap::size() const { return iImp->iData.size(); } //! Return object number of the bitmap. inline int Bitmap::objNum() const { return iImp->iObjNum; } //! Set object number of the bitmap. inline void Bitmap::setObjNum(int objNum) const { iImp->iObjNum = objNum; } //! Return cached bitmap for rendering. inline Bitmap::MRenderData *Bitmap::renderData() const { return iImp->iRender; } //! Two bitmaps are equal if they share the same data. inline bool Bitmap::operator==(const Bitmap &rhs) const { return iImp == rhs.iImp; } //! Two bitmaps are equal if they share the same data. inline bool Bitmap::operator!=(const Bitmap &rhs) const { return iImp != rhs.iImp; } //! Less operator, to be able to sort bitmaps. /*! The checksum is used, when it is equal, the shared address. This guarantees that bitmaps that are == (share their implementation) are next to each other, and blocks of them are next to blocks that are identical in contents. */ inline bool Bitmap::operator<(const Bitmap &rhs) const { return (iImp->iChecksum < rhs.iImp->iChecksum || (iImp->iChecksum == rhs.iImp->iChecksum && iImp < rhs.iImp)); } } // namespace // -------------------------------------------------------------------- #endif ipe-7.1.4/src/ipetoipe/0000755000175000017500000000000012120621776014563 5ustar otfriedotfriedipe-7.1.4/src/ipetoipe/Makefile0000644000175000017500000000133212120621776016222 0ustar otfriedotfried# -------------------------------------------------------------------- # Makefile for Ipetoipe # -------------------------------------------------------------------- OBJDIR = $(BUILDDIR)/obj/ipetoipe include ../common.mak TARGET = $(call exe_target,ipetoipe) CPPFLAGS += -I../include LIBS += -L$(buildlib) -lipe all: $(TARGET) sources = ipetoipe.cpp $(TARGET): $(objects) $(MAKE_BINDIR) $(CXX) $(LDFLAGS) -o $@ $^ $(LIBS) clean: @-rm -f $(objects) $(TARGET) $(DEPEND) $(DEPEND): Makefile $(MAKE_DEPEND) -include $(DEPEND) install: $(TARGET) $(INSTALL_DIR) $(INSTALL_ROOT)$(IPEBINDIR) $(INSTALL_PROGRAMS) $(TARGET) $(INSTALL_ROOT)$(IPEBINDIR) # -------------------------------------------------------------------- ipe-7.1.4/src/ipetoipe/ipetoipe.cpp0000644000175000017500000001731612120621776017115 0ustar otfriedotfried// -------------------------------------------------------------------- // ipetoipe // -------------------------------------------------------------------- /* This file is part of the extensible drawing editor Ipe. Copyright (C) 1993-2013 Otfried Cheong Ipe is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. As a special exception, you have permission to link Ipe with the CGAL library and distribute executables, as long as you follow the requirements of the Gnu General Public License in regard to all of the software in the executable aside from CGAL. Ipe 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 General Public License for more details. You should have received a copy of the GNU General Public License along with Ipe; if not, you can find it at "http://www.gnu.org/copyleft/gpl.html", or write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ #include "ipedoc.h" using ipe::Document; using ipe::String; static int topdforps(Document *doc, String src, String dst, Document::TFormat fm, uint flags, int fromPage = -1, int toPage = -1, int viewNo = -1) { if (fm == Document::EEps) { if (viewNo < 0 && doc->countTotalViews() > 1) { fprintf(stderr, "The document contains %d views, " "cannot convert to EPS format.\n", doc->countTotalViews()); return 1; } bool trans = doc->hasTransparency(); bool grad = doc->hasGradients(); if (!trans && !grad) { int res = doc->runLatex(); if (res) return res; } bool ttf = doc->hasTrueTypeFonts(); if (trans || grad || ttf) { fprintf(stderr, "The document uses the following features:\n"); if (trans) fprintf(stderr, " - transparency\n"); if (grad) fprintf(stderr, " - gradients\n"); if (ttf) fprintf(stderr, " - Truetype fonts\n"); fprintf(stderr, "Ipe does not support these features for Postscript output.\n" "You can save as PDF, and use pdftops to create a " "Postscript file.\n"); return 1; } } else { int res = doc->runLatex(); if (res) return res; } bool result = false; if (viewNo >= 0) { result = doc->exportView(dst.z(), fm, flags, fromPage, viewNo); } else if (toPage >= 0) { result = doc->exportPages(dst.z(), flags, fromPage, toPage); } else { result = doc->save(dst.z(), fm, flags); } if (!result) { fprintf(stderr, "Failed to save or export document!\n"); return 1; } if (flags & Document::EExport) fprintf(stderr, "Warning: the exported file contains no Ipe markup.\n" "It cannot be read by Ipe - make sure you keep the original!\n"); return 0; } static void usage() { fprintf(stderr, "Usage: ipetoipe ( -xml | -eps | -pdf ) " "infile [ outfile ]\n" "Ipetoipe converts between the different Ipe file formats.\n" " -export : output contains no Ipe markup.\n" " -pages : export only these pages (implies -export).\n" " -view : export only this view (implies -export).\n" " -markedview " ": export only marked views on marked pages (implies -export).\n" " -runlatex : run Latex even for XML output.\n" " -nocolor : avoid any color commands in EPS output.\n" " -nozip: : do not compress PDF streams.\n" ); exit(1); } int main(int argc, char *argv[]) { ipe::Platform::initLib(ipe::IPELIB_VERSION); // ensure at least two arguments (handles -help as well :-) if (argc < 3) usage(); Document::TFormat frm = Document::EUnknown; if (!strcmp(argv[1], "-xml")) frm = Document::EXml; else if (!strcmp(argv[1], "-eps")) frm = Document::EEps; else if (!strcmp(argv[1], "-pdf")) frm = Document::EPdf; if (frm == Document::EUnknown) usage(); uint flags = Document::ESaveNormal; bool runLatex = false; int fromPage = -1; int toPage = -1; int viewNo = -1; int i = 2; String infile; String outfile; while (i < argc) { if (!strcmp(argv[i], "-export")) { flags |= Document::EExport; ++i; } else if (!strcmp(argv[i], "-view")) { if (sscanf(argv[i+1], "%d-%d", &fromPage, &viewNo) != 2) usage(); flags |= Document::EExport; i += 2; } else if (!strcmp(argv[i], "-pages")) { if (sscanf(argv[i+1], "%d-%d", &fromPage, &toPage) != 2) usage(); flags |= Document::EExport; i += 2; } else if (!strcmp(argv[i], "-markedview")) { flags |= Document::EMarkedView; flags |= Document::EExport; ++i; } else if (!strcmp(argv[i], "-runlatex")) { runLatex = true; ++i; } else if (!strcmp(argv[i], "-nocolor")) { flags |= Document::ENoColor; ++i; } else if (!strcmp(argv[i], "-nozip")) { flags |= Document::ENoZip; ++i; } else { // last one or two arguments must be filenames infile = argv[i]; ++i; if (i < argc) { outfile = argv[i]; ++i; } if (i != argc) usage(); } } if (infile.empty()) usage(); if ((flags & Document::EExport) && frm == Document::EXml) { fprintf(stderr, "-export only available with -pdf and -eps.\n"); exit(1); } if (toPage >= 0 && frm != Document::EPdf) { fprintf(stderr, "-pages only available with -pdf.\n"); exit(1); } if (toPage >= 0 && viewNo >= 0) { fprintf(stderr, "cannot specify both -pages and -view.\n"); exit(1); } if (outfile.empty()) { outfile = infile; String ext = infile.right(4); if (ext == ".ipe" || ext == ".pdf" || ext == ".xml" || ext == ".eps") outfile = infile.left(infile.size() - 4); switch (frm) { case Document::EXml: outfile += ".ipe"; break; case Document::EPdf: outfile += ".pdf"; break; case Document::EEps: outfile += ".eps"; default: break; } if (outfile == infile) { fprintf(stderr, "Cannot guess output filename.\n"); exit(1); } } IpeAutoPtr doc(Document::loadWithErrorReport(infile.z())); if (!doc.ptr()) return 1; fprintf(stderr, "Document %s has %d pages (%d views)\n", infile.z(), doc->countPages(), doc->countTotalViews()); // check frompage, topage, viewno if (toPage >= 0) { if (fromPage <= 0 || fromPage > toPage || toPage > doc->countPages()) { fprintf(stderr, "incorrect -pages specification.\n"); exit(1); } --fromPage; --toPage; } else if (fromPage >= 0) { if (fromPage <= 0 || fromPage > doc->countPages() || viewNo <= 0 || viewNo > doc->page(fromPage - 1)->countViews()) { fprintf(stderr, "incorrect -view specification.\n"); exit(1); } --fromPage; --viewNo; } char buf[64]; sprintf(buf, "ipetoipe %d.%d.%d", ipe::IPELIB_VERSION / 10000, (ipe::IPELIB_VERSION / 100) % 100, ipe::IPELIB_VERSION % 100); Document::SProperties props = doc->properties(); props.iCreator = buf; doc->setProperties(props); switch (frm) { case Document::EXml: if (runLatex) return topdforps(doc.ptr(), infile, outfile, Document::EXml, flags); else doc->save(outfile.z(), Document::EXml, Document::ESaveNormal); default: return 0; case Document::EPdf: return topdforps(doc.ptr(), infile, outfile, Document::EPdf, flags, fromPage, toPage, viewNo); case Document::EEps: return topdforps(doc.ptr(), infile, outfile, Document::EEps, flags, fromPage, toPage, viewNo); } } // -------------------------------------------------------------------- ipe-7.1.4/src/ipe6upgrade/0000755000175000017500000000000012120621776015160 5ustar otfriedotfriedipe-7.1.4/src/ipe6upgrade/ipe6upgrade.cpp0000644000175000017500000004506112120621776020105 0ustar otfriedotfried// -------------------------------------------------------------------- // Ipe6upgrade // -------------------------------------------------------------------- /* This file is part of the extensible drawing editor Ipe. Copyright (C) 1993-2013 Otfried Cheong Ipe is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. As a special exception, you have permission to link Ipe with the CGAL library and distribute executables, as long as you follow the requirements of the Gnu General Public License in regard to all of the software in the executable aside from CGAL. Ipe 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 General Public License for more details. You should have received a copy of the GNU General Public License along with Ipe; if not, you can find it at "http://www.gnu.org/copyleft/gpl.html", or write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ #include "ipexml.h" #include "ipeattributes.h" using namespace ipe; // -------------------------------------------------------------------- struct Attributes { String textsize; String marksize; String markshape; String stroke; String fill; String dashStyle; String pen; String cap; String join; String fillrule; }; // -------------------------------------------------------------------- static const char *standardSheet = "\n" "\n" "\n" "\n" "\n" "\n" "\n" "\n" "\n" "\n" "\n" "\n" "\n" "\n" "\n" "\n" "\n" "\n" "\n" "\n" "\n" "\n" "\n" "\n" "\n" "\n" "\n" "\n" "\n" "\n" "\n" "\n" "\n" "\n" "\n" "0.6 0 0 0.6 0 0 e 0.4 0 0 0.4 0 0 e\n" "\n" "\n" "\n" "0.6 0 0 0.6 0 0 e\n" "\n" "\n" "\n" "0.5 0 0 0.5 0 0 e\n" "\n" "0.6 0 0 0.6 0 0 e 0.4 0 0 0.4 0 0 e\n" "\n" "\n" "\n" "-0.6 -0.6 m 0.6 -0.6 l 0.6 0.6 l -0.6 0.6 l h " "-0.4 -0.4 m 0.4 -0.4 l 0.4 0.4 l -0.4 0.4 l h" "\n" "\n" "\n" "-0.6 -0.6 m 0.6 -0.6 l 0.6 0.6 l -0.6 0.6 l h" "\n" "\n" "\n" "-0.5 -0.5 m 0.5 -0.5 l 0.5 0.5 l -0.5 0.5 l h" "\n" "-0.6 -0.6 m 0.6 -0.6 l 0.6 0.6 l -0.6 0.6 l h" "-0.4 -0.4 m 0.4 -0.4 l 0.4 0.4 l -0.4 0.4 l h" "\n" "\n" "\n" "-0.43 -0.57 m 0.57 0.43 l 0.43 0.57 l -0.57 -0.43 l h" "\n" "-0.43 0.57 m 0.57 -0.43 l 0.43 -0.57 l -0.57 0.43 l h\n" "\n" "\n" "\n" "\n" "\n"; // -------------------------------------------------------------------- class Parser : public XmlParser { public: enum { ESuccess = 0, ENotIpe6 = 1, ESyntaxError = 2 }; explicit Parser(DataSource &source, Stream &out); int parseDocument(); bool parsePage(); bool parseObject(String tag, const Attributes &a); bool parseGroup(const XmlAttributes &attr, const Attributes &a); bool parseStyle(); bool parseBitmap(); private: void writeAttr(const XmlAttributes &att, String s, String grs = String()); void writeAttr(const XmlAttributes &att); void writeTag(String tag, const XmlAttributes &att, String data = String()); private: Stream &iStream; double iTextStretch; Rect iMediaBox; bool iUseCropBox; }; // -------------------------------------------------------------------- Parser::Parser(DataSource &source, Stream &out) : XmlParser(source), iStream(out) { // nothing } int Parser::parseDocument() { String tag = parseToTag(); if (tag == "?xml") { XmlAttributes attr; if (!parseAttributes(attr)) return ESyntaxError; tag = parseToTag(); } if (tag != "ipe") return ESyntaxError; XmlAttributes attr; if (!parseAttributes(attr)) return ESyntaxError; String str; iStream << "\n"; iStream << "\n"; iStream << "= 70000) return ENotIpe6; } iStream << " version=\"70000\""; iStream << " creator=\"ipe6upgrade\">\n"; // up to pre27 media size was in bool needMediaSheet = false; iUseCropBox = true; Vector paper; tag = parseToTag(); if (tag == "info") { XmlAttributes att; if (!parseAttributes(att)) return ESyntaxError; if (att.has("media", str)) { Lex lex(str); Vector mbmin; lex >> mbmin.x >> mbmin.y >> paper.x >> paper.y; needMediaSheet = true; } iUseCropBox = (att.has("bbox", str) && str == "yes"); iStream << "\n"; tag = parseToTag(); } if (tag == "preamble") { XmlAttributes att; if (!parseAttributes(att)) return false; if (!parsePCDATA("preamble", str)) return false; iStream << ""; iStream.putXmlString(str); iStream << "\n"; tag = parseToTag(); } iStream << standardSheet; if (needMediaSheet) { iStream << "\n"; iStream << "\n"; iStream << "\n"; } while (tag == "ipestyle" || tag == "bitmap") { if (tag == "ipestyle") { if (!parseStyle()) return ESyntaxError; } else { // tag == "bitmap" if (!parseBitmap()) return ESyntaxError; } tag = parseToTag(); } while (tag == "page") { if (!parsePage()) return ESyntaxError; tag = parseToTag(); } if (tag != "/ipe") return ESyntaxError; iStream << "\n"; return ESuccess; } //! Parse an Bitmap. /*! On calling, stream must be just past \c bitmap. */ bool Parser::parseBitmap() { XmlAttributes att; if (!parseAttributes(att)) return false; String bits; if (!att.slash() && !parsePCDATA("bitmap", bits)) return false; writeTag("bitmap", att, bits); return true; } //! Parse an Page. /*! On calling, stream must be just past \c page. */ bool Parser::parsePage() { XmlAttributes att; if (!parseAttributes(att)) return false; iStream << "\n"; String tag = parseToTag(); while (tag == "layer" || tag == "view") { XmlAttributes att; if (!parseAttributes(att)) return false; if (tag == "layer") { iStream << "\n"; } else { // effects are not supported by ipe6upgrade iStream << "\n"; } tag = parseToTag(); } Attributes a; for (;;) { if (tag == "/page") { iStream << "\n"; return true; } if (!parseObject(tag, a)) return false; tag = parseToTag(); } return true; } bool Parser::parseGroup(const XmlAttributes &attr, const Attributes &a) { iStream << "\n"; Attributes a1 = a; if (a.textsize.empty()) a1.textsize = attr["textsize"]; if (a.marksize.empty()) a1.marksize = attr["marksize"]; if (a.markshape.empty()) a1.markshape = attr["markshape"]; if (a.stroke.empty()) a1.stroke = attr["stroke"]; if (a.fill.empty()) a1.fill = attr["fill"]; if (a.dashStyle.empty()) a1.dashStyle = attr["dash"]; if (a.pen.empty()) a1.pen = attr["pen"]; if (a.cap.empty()) a1.cap = attr["cap"]; if (a.join.empty()) a1.join = attr["join"]; if (a.fillrule.empty()) a1.fillrule = attr["fillrule"]; String tag = parseToTag(); for (;;) { if (tag == "/group") { iStream << "\n"; return true; } if (!parseObject(tag, a1)) return false; tag = parseToTag(); } } static const char *const marktypes[] = { "circle(sx)", "disk(sx)", "box(sx)", "square(sx)", "cross(sx)", "fdisk(sfx)", "fsquare(sfx)" }; //! Parse an Object. /*! On calling, stream must be just past the tag. */ bool Parser::parseObject(String tag, const Attributes &a) { XmlAttributes attr; if (!parseAttributes(attr)) return false; if (tag == "group") return parseGroup(attr, a); String pcdata; if (!attr.slash() && !parsePCDATA(tag, pcdata)) return false; if (tag == "image") { writeTag(tag, attr, pcdata); } else if (tag == "ref") { writeTag("use", attr, pcdata); } else if (tag == "mark") { String t; if (a.markshape.empty()) t = attr["shape"]; else t = a.markshape; int typ = Lex(t).getInt(); if (!a.fill.isEmpty() || !attr["fill"].isEmpty()) { if (typ == 1) typ = 6; else if (typ == 3) typ = 7; } iStream << "\n"; } else if (tag == "text") { iStream << ""; iStream.putXmlString(pcdata); iStream << "\n"; } else if (tag == "path") { iStream << ""; iStream.putXmlString(pcdata); iStream << "\n"; } else return false; return true; } // these tags are left unchanged static const char *const styledefs[] = { "titlestyle", "layout", "cmap", "textstyle", "pathstyle", "color", "dashstyle", "textsize", "textstretch", "marksize", "arrowsize" }; //! Parse a style sheet. /*! On calling, stream must be just past the style tag. */ bool Parser::parseStyle() { XmlAttributes att; if (!parseAttributes(att)) return false; String tag = parseToTag(); if (tag == "/ipestyle") // empty sheet, return without writing anything return true; iStream << "\n"; while (tag != "/ipestyle") { if (tag == "bitmap") { if (!parseBitmap()) return false; } else if (tag == "template") { if (!parseAttributes(att)) return false; iStream << "\n"; String tag1 = parseToTag(); Attributes a; if (!parseObject(tag1, a)) return false; if (parseToTag() != "/template") return false; iStream << "\n"; } else if (tag == "preamble") { if (!parseAttributes(att)) return false; String pcdata; if (!att.slash() && !parsePCDATA(tag, pcdata)) return false; writeTag("preamble", att, pcdata); } else if (tag == "textmatrix" || tag == "media" || tag == "margins" || tag == "shading") { // Keep old style sheets parsing correctly, but ignore them if (!parseAttributes(att) || !att.slash()) return false; } else if (tag == "marksize") { if (!parseAttributes(att) || !att.slash()) return false; writeTag("symbolsize", att); } else if (tag == "angle") { if (!parseAttributes(att) || !att.slash()) return false; writeTag("anglesize", att); } else if (tag == "grid") { if (!parseAttributes(att) || !att.slash()) return false; writeTag("gridsize", att); } else if (tag == "linewidth") { if (!parseAttributes(att) || !att.slash()) return false; writeTag("pen", att); } else if (tag == "layout") { if (!parseAttributes(att) || !att.slash()) return false; if (!iUseCropBox) att.add("crop", "no"); writeTag("layout", att); } else { // only standard tags remain uint i = 0; while (i < (sizeof(styledefs)/sizeof(const char *)) && tag != styledefs[i]) ++i; if (i == (sizeof(styledefs)/sizeof(const char *))) return false; if (!parseAttributes(att) || !att.slash()) return false; if (tag == "color") { if (att["value"] == "black") att.add("value", "0"); else if (att["value"] == "white") att.add("value", "1"); } writeTag(tag, att); } tag = parseToTag(); } iStream << "\n"; return true; } void Parser::writeAttr(const XmlAttributes &att, String s, String grs) { String str = grs; if (!str.empty() || att.has(s, str)) { iStream << " " << s << "=\""; iStream.putXmlString(str); iStream << "\""; } } void Parser::writeAttr(const XmlAttributes &att) { for (XmlAttributes::const_iterator it = att.begin(); it != att.end(); ++it) { String name = it->first; String value = it->second; iStream << " " << name << "=\""; iStream.putXmlString(value); iStream << "\""; } } void Parser::writeTag(String tag, const XmlAttributes &att, String data) { iStream << "<" << tag; writeAttr(att); if (data.empty()) { iStream << "/>\n"; } else { iStream << ">"; iStream.putXmlString(data); iStream << "\n"; } } // -------------------------------------------------------------------- static void usage() { fprintf(stderr, "Usage: ipe6upgrade [ ]\n" "Ipe6upgrade reads the XML format generated by any version of" " Ipe 6,\nand writes the XML Format of Ipe 7.0.\n"); exit(1); } int main(int argc, char *argv[]) { Platform::initLib(IPELIB_VERSION); // ensure two or three arguments if (argc != 2 && argc != 3) usage(); const char *src = argv[1]; String dst; if (argc == 3) { dst = argv[2]; } else { String s = src; if (s.right(4) == ".xml") dst = s.left(s.size() - 3) + "ipe"; else dst = s + ".ipe7"; } std::FILE *fd = std::fopen(src, "rb"); if (!fd) { std::fprintf(stderr, "Could not open '%s'\n", src); exit(1); } std::FILE *out = std::fopen(dst.z(), "wb"); if (!out) { fprintf(stderr, "Could not open '%s' for writing.\n", dst.z()); exit(3); } FileSource source(fd); FileStream sink(out); Parser parser(source, sink); int result = parser.parseDocument(); std::fclose(fd); sink.close(); std::fclose(out); if (result == Parser::ENotIpe6) { fprintf(stderr, "The input file was not created by a version of Ipe 6.\n"); exit(1); } if (result == Parser::ESyntaxError) { fprintf(stderr, "Error parsing at position %d\n", parser.parsePosition()); exit(2); } return 0; } // -------------------------------------------------------------------- ipe-7.1.4/src/ipe6upgrade/Makefile0000644000175000017500000000140312120621776016616 0ustar otfriedotfried# -------------------------------------------------------------------- # Makefile for Ipe6upgrade # -------------------------------------------------------------------- OBJDIR = $(BUILDDIR)/obj/ipe6upgrade include ../common.mak TARGET = $(call exe_target,ipe6upgrade) CPPFLAGS += -I../include LIBS += -L$(buildlib) -lipe #LIBS += $(buildlib)/ipe.dll all: $(TARGET) sources = ipe6upgrade.cpp $(TARGET): $(objects) $(MAKE_BINDIR) $(CXX) $(LDFLAGS) -o $@ $^ $(LIBS) clean: @-rm -f $(objects) $(TARGET) $(DEPEND) $(DEPEND): Makefile $(MAKE_DEPEND) -include $(DEPEND) install: $(TARGET) $(INSTALL_DIR) $(INSTALL_ROOT)$(IPEBINDIR) $(INSTALL_PROGRAMS) $(TARGET) $(INSTALL_ROOT)$(IPEBINDIR) # -------------------------------------------------------------------- ipe-7.1.4/src/ipelua/0000755000175000017500000000000012120621776014224 5ustar otfriedotfriedipe-7.1.4/src/ipelua/ipeluaipelet.cpp0000644000175000017500000001373112120621776017417 0ustar otfriedotfried// -------------------------------------------------------------------- // ipeluaipelets.cpp // -------------------------------------------------------------------- /* This file is part of the extensible drawing editor Ipe. Copyright (C) 1993-2013 Otfried Cheong Ipe is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. As a special exception, you have permission to link Ipe with the CGAL library and distribute executables, as long as you follow the requirements of the Gnu General Public License in regard to all of the software in the executable aside from CGAL. Ipe 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 General Public License for more details. You should have received a copy of the GNU General Public License along with Ipe; if not, you can find it at "http://www.gnu.org/copyleft/gpl.html", or write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ #include "ipelua.h" #ifdef WIN32 #include #else #include #endif using namespace ipe; using namespace ipelua; typedef Ipelet *(*PNewIpeletFn)(); // -------------------------------------------------------------------- static int ipelet_destructor(lua_State *L) { ipeDebug("Ipelet destructor"); Ipelet **p = check_ipelet(L, 1); delete *p; *p = 0; return 0; } static int ipelet_tostring(lua_State *L) { check_ipelet(L, 1); lua_pushfstring(L, "Ipelet@%p", lua_topointer(L, 1)); return 1; } // -------------------------------------------------------------------- int ipelua::ipelet_constructor(lua_State *L) { String fname(luaL_checkstring(L, 1)); #ifdef WIN32 fname += ".dll"; #else fname += ".so"; #endif ipeDebug("Loading dll '%s'", fname.z()); PNewIpeletFn pIpelet = 0; #ifdef WIN32 HMODULE hMod = LoadLibraryA(fname.z()); if (hMod) { pIpelet = (PNewIpeletFn) GetProcAddress(hMod, "newIpelet"); if (!pIpelet) pIpelet = (PNewIpeletFn) GetProcAddress(hMod, "_newIpelet"); } #else void *handle = dlopen(fname.z(), RTLD_NOW); if (handle) { pIpelet = (PNewIpeletFn) dlsym(handle, "newIpelet"); if (!pIpelet) pIpelet = (PNewIpeletFn) dlsym(handle, "_newIpelet"); } #endif if (pIpelet) { Ipelet **p = (Ipelet **) lua_newuserdata(L, sizeof(Ipelet *)); *p = 0; luaL_getmetatable(L, "Ipe.ipelet"); lua_setmetatable(L, -2); Ipelet *ipelet = pIpelet(); if (ipelet == 0) { lua_pushnil(L); lua_pushstring(L, "ipelet returns no object"); return 2; } if (ipelet->ipelibVersion() != IPELIB_VERSION) { delete ipelet; lua_pushnil(L); lua_pushstring(L, "ipelet linked against older version of Ipelib"); return 2; } *p = ipelet; // ipeDebug("Ipelet '%s' loaded", fname.z()); return 1; } else { lua_pushnil(L); #ifdef WIN32 lua_pushstring(L, "Error loading Ipelet DLL"); #else lua_pushfstring(L, "Error loading Ipelet: %s", dlerror()); #endif return 2; } } // -------------------------------------------------------------------- class Helper : public IpeletHelper { public: Helper(lua_State *L0, int luahelper); ~Helper(); virtual void message(const char *msg); virtual int messageBox(const char *text, const char *details, int buttons); virtual bool getString(const char *prompt, String &str); private: lua_State *L; int iHelper; }; Helper::Helper(lua_State *L0, int luahelper) { L = L0; iHelper = luahelper; } Helper::~Helper() { luaL_unref(L, LUA_REGISTRYINDEX, iHelper); } void Helper::message(const char *msg) { lua_rawgeti(L, LUA_REGISTRYINDEX, iHelper); lua_getfield(L, -1, "message"); lua_pushvalue(L, -2); // luahelper lua_remove(L, -3); lua_pushstring(L, msg); lua_call(L, 2, 0); } int Helper::messageBox(const char *text, const char *details, int buttons) { lua_rawgeti(L, LUA_REGISTRYINDEX, iHelper); lua_getfield(L, -1, "messageBox"); lua_pushvalue(L, -2); // luahelper lua_remove(L, -3); lua_pushstring(L, text); if (details) lua_pushstring(L, details); else lua_pushnil(L); lua_pushnumber(L, buttons); lua_call(L, 4, 1); if (lua_isnumber(L, -1)) return int(lua_tonumber(L, -1)); else return 0; } bool Helper::getString(const char *prompt, String &str) { lua_rawgeti(L, LUA_REGISTRYINDEX, iHelper); lua_getfield(L, -1, "getString"); lua_pushvalue(L, -2); // luahelper lua_remove(L, -3); lua_pushstring(L, prompt); lua_call(L, 2, 1); if (lua_isstring(L, -1)) { str = lua_tostring(L, -1); return true; } else return false; } // -------------------------------------------------------------------- static int ipelet_run(lua_State *L) { Ipelet **p = check_ipelet(L, 1); int num = luaL_checkint(L, 2) - 1; // Lua counts starting from one IpeletData data; data.iPage = check_page(L, 3)->page; data.iDoc = *check_document(L, 4); data.iPageNo = luaL_checkint(L, 5); data.iView = luaL_checkint(L, 6); data.iLayer = check_layer(L, 7, data.iPage); check_allattributes(L, 8, data.iAttributes); // data.iSnap; lua_pushvalue(L, 9); int luahelper = luaL_ref(L, LUA_REGISTRYINDEX); Helper helper(L, luahelper); bool result = (*p)->run(num, &data, &helper); lua_pushboolean(L, result); return 1; } // -------------------------------------------------------------------- static const struct luaL_Reg ipelet_methods[] = { { "__tostring", ipelet_tostring }, { "__gc", ipelet_destructor }, { "run", ipelet_run }, { NULL, NULL } }; // -------------------------------------------------------------------- int ipelua::open_ipelets(lua_State *L) { make_metatable(L, "Ipe.ipelet", ipelet_methods); return 0; } // -------------------------------------------------------------------- ipe-7.1.4/src/ipelua/ipelua.h0000644000175000017500000001535612120621776015666 0ustar otfriedotfried// -------------------------------------------------------------------- // ipelua.h // -------------------------------------------------------------------- /* This file is part of the extensible drawing editor Ipe. Copyright (C) 1993-2013 Otfried Cheong Ipe is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. As a special exception, you have permission to link Ipe with the CGAL library and distribute executables, as long as you follow the requirements of the Gnu General Public License in regard to all of the software in the executable aside from CGAL. Ipe 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 General Public License for more details. You should have received a copy of the GNU General Public License along with Ipe; if not, you can find it at "http://www.gnu.org/copyleft/gpl.html", or write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ #ifndef IPELUA_H #define IPELUA_H extern "C" { #include #include #include } #include "ipestyle.h" #include "ipepage.h" #include "ipeshape.h" #include "ipedoc.h" #include "ipelet.h" namespace ipelua { struct SSheet { bool owned; ipe::StyleSheet *sheet; }; struct SCascade { bool owned; ipe::Cascade *cascade; }; struct SPage { bool owned; ipe::Page *page; }; struct SObject { bool owned; ipe::Object *obj; }; inline ipe::Document **check_document(lua_State *L, int i) { return (ipe::Document **) luaL_checkudata(L, i, "Ipe.document"); } inline ipe::Vector *check_vector(lua_State *L, int i) { return (ipe::Vector *) luaL_checkudata(L, i, "Ipe.vector"); } inline ipe::Matrix *check_matrix(lua_State *L, int i) { return (ipe::Matrix *) luaL_checkudata(L, i, "Ipe.matrix"); } inline ipe::Rect *check_rect(lua_State *L, int i) { return (ipe::Rect *) luaL_checkudata(L, i, "Ipe.rect"); } inline ipe::Line *check_line(lua_State *L, int i) { return (ipe::Line *) luaL_checkudata(L, i, "Ipe.line"); } inline ipe::Segment *check_segment(lua_State *L, int i) { return (ipe::Segment *) luaL_checkudata(L, i, "Ipe.segment"); } inline ipe::Bezier *check_bezier(lua_State *L, int i) { return (ipe::Bezier *) luaL_checkudata(L, i, "Ipe.bezier"); } inline ipe::Arc *check_arc(lua_State *L, int i) { return (ipe::Arc *) luaL_checkudata(L, i, "Ipe.arc"); } inline SObject *check_object(lua_State *L, int i) { return (SObject *) luaL_checkudata(L, i, "Ipe.object"); } inline SSheet *check_sheet(lua_State *L, int i) { return (SSheet *) luaL_checkudata(L, i, "Ipe.sheet"); } inline SCascade *check_cascade(lua_State *L, int i) { return (SCascade *) luaL_checkudata(L, i, "Ipe.cascade"); } inline SPage *check_page(lua_State *L, int i) { return (SPage *) luaL_checkudata(L, i, "Ipe.page"); } inline ipe::Ipelet **check_ipelet(lua_State *L, int i) { return (ipe::Ipelet **) luaL_checkudata(L, i, "Ipe.ipelet"); } // -------------------------------------------------------------------- extern void make_metatable(lua_State *L, const char *name, const struct luaL_Reg *methods); extern bool is_type(lua_State *L, int ud, const char *tname); extern const char *const linejoin_names[]; extern const char *const linecap_names[]; extern const char *const fillrule_names[]; extern ipe::String check_filename(lua_State *L, int index); // geo extern void push_vector(lua_State *L, const ipe::Vector &v); extern int vector_constructor(lua_State *L); extern int direction_constructor(lua_State *L); extern void push_matrix(lua_State *L, const ipe::Matrix &m); extern int matrix_constructor(lua_State *L); extern int rotation_constructor(lua_State *L); extern int translation_constructor(lua_State *L); extern void push_rect(lua_State *L, const ipe::Rect &r); extern int rect_constructor(lua_State *L); extern void push_line(lua_State *L, const ipe::Line &l); extern int line_constructor(lua_State *L); extern int line_through(lua_State *L); extern int line_bisector(lua_State *L); extern void push_segment(lua_State *L, const ipe::Segment &s); extern int segment_constructor(lua_State *L); extern void push_bezier(lua_State *L, const ipe::Bezier &b); extern int bezier_constructor(lua_State *L); extern int quad_constructor(lua_State *L); extern void push_arc(lua_State *L, const ipe::Arc &a); extern int arc_constructor(lua_State *L); // obj extern void push_string(lua_State *L, ipe::String str); extern void push_color(lua_State *L, ipe::Color color); extern void push_attribute(lua_State *L, ipe::Attribute att); extern ipe::Attribute check_color_attribute(lua_State *L, int i); extern ipe::Attribute check_number_attribute(lua_State *L, int i); extern ipe::Attribute check_bool_attribute(lua_State *L, int i); extern ipe::Color check_color(lua_State *L, int i); extern ipe::Attribute check_property(ipe::Property prop, lua_State *L, int i); extern void check_allattributes(lua_State *L, int i, ipe::AllAttributes &all); extern void push_object(lua_State *L, ipe::Object *obj, bool owned = true); extern int reference_constructor(lua_State *L); extern int text_constructor(lua_State *L); extern int path_constructor(lua_State *L); extern int group_constructor(lua_State *L); extern int xml_constructor(lua_State *L); extern ipe::Shape check_shape(lua_State *L, int index); // style extern void push_sheet(lua_State *L, ipe::StyleSheet *s, bool owned = true); extern void push_cascade(lua_State *L, ipe::Cascade *s, bool owned = true); extern int sheet_constructor(lua_State *L); extern int cascade_constructor(lua_State *L); extern int test_option(lua_State *L, int i, const char * const *names); // page extern void push_page(lua_State *L, ipe::Page *page, bool owned = true); extern int check_layer(lua_State *L, int i, ipe::Page *p); extern int check_viewno(lua_State *L, int i, ipe::Page *p, int extra = 0); extern int page_constructor(lua_State *L); // ipelet extern int ipelet_constructor(lua_State *L); // open components extern int open_ipegeo(lua_State *L); extern int open_ipeobj(lua_State *L); extern int open_ipestyle(lua_State *L); extern int open_ipepage(lua_State *L); extern int open_ipelets(lua_State *L); } // namespace extern "C" int luaopen_ipe(lua_State *L); // -------------------------------------------------------------------- #endif ipe-7.1.4/src/ipelua/ipelib.cpp0000644000175000017500000004167312120621776016207 0ustar otfriedotfried// -------------------------------------------------------------------- // ipelib.cpp // -------------------------------------------------------------------- /* This file is part of the extensible drawing editor Ipe. Copyright (C) 1993-2013 Otfried Cheong Ipe is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. As a special exception, you have permission to link Ipe with the CGAL library and distribute executables, as long as you follow the requirements of the Gnu General Public License in regard to all of the software in the executable aside from CGAL. Ipe 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 General Public License for more details. You should have received a copy of the GNU General Public License along with Ipe; if not, you can find it at "http://www.gnu.org/copyleft/gpl.html", or write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ #include "ipelua.h" #include "ipedoc.h" #include using namespace ipe; using namespace ipelua; // -------------------------------------------------------------------- static const char * const format_name[] = { "xml", "pdf", "eps", "ipe5", "unknown" }; void ipelua::make_metatable(lua_State *L, const char *name, const struct luaL_Reg *methods) { luaL_newmetatable(L, name); lua_pushstring(L, "__index"); lua_pushvalue(L, -2); /* pushes the metatable */ lua_settable(L, -3); /* metatable.__index = metatable */ luaL_setfuncs(L, methods, 0); lua_pop(L, 1); } bool ipelua::is_type(lua_State *L, int ud, const char *tname) { if (lua_isuserdata(L, ud) && lua_getmetatable(L, ud)) { lua_getfield(L, LUA_REGISTRYINDEX, tname); if (lua_rawequal(L, -1, -2)) { lua_pop(L, 2); return true; } } return false; } String ipelua::check_filename(lua_State *L, int index) { // TODO: local encoding! return String(luaL_checkstring(L, index)); } // -------------------------------------------------------------------- // Document // -------------------------------------------------------------------- static int document_constructor(lua_State *L) { bool has_fname = (lua_gettop(L) > 0); Document **d = (Document **) lua_newuserdata(L, sizeof(Document *)); *d = 0; luaL_getmetatable(L, "Ipe.document"); lua_setmetatable(L, -2); // should we load a document? if (has_fname) { String fname = check_filename(L, 1); int reason; *d = Document::load(fname.z(), reason); if (*d) return 1; lua_pop(L, 1); // pop empty document udata lua_pushnil(L); // return nil and ... switch (reason) { case Document::EVersionTooOld: lua_pushliteral(L, "The Ipe version of this document is too old"); break; case Document::EVersionTooRecent: lua_pushliteral(L, "The document was created by a newer version of Ipe"); break; case Document::EFileOpenError: lua_pushfstring(L, "Error opening file: %s", strerror(errno)); break; default: lua_pushfstring(L, "Parsing error at position %d", reason); break; } lua_pushnumber(L, reason); return 3; } else { // create new empty document *d = new Document(); // create the first page (*d)->insert(0, Page::basic()); return 1; } } static int document_destruct(lua_State *L) { Document **d = check_document(L, 1); delete (*d); *d = 0; return 0; } static int document_tostring(lua_State *L) { check_document(L, 1); lua_pushfstring(L, "Document@%p", lua_topointer(L, 1)); return 1; } // -------------------------------------------------------------------- static int check_pageno(lua_State *L, int i, Document *d, int extra = 0) { int n = luaL_checkint(L, i); luaL_argcheck(L, 1 <= n && n <= d->countPages() + extra, i, "invalid page number"); return n - 1; } static int document_index(lua_State *L) { Document **d = check_document(L, 1); if (lua_type(L, 2) == LUA_TNUMBER) { int n = check_pageno(L, 2, *d); push_page(L, (*d)->page(n), false); } else { const char *key = luaL_checkstring(L, 2); if (!luaL_getmetafield(L, 1, key)) lua_pushnil(L); } return 1; } // Document --> int static int document_len(lua_State *L) { Document **d = check_document(L, 1); lua_pushinteger(L, (*d)->countPages()); return 1; } // arguments: document, counter static int document_page_iterator(lua_State *L) { Document **d = check_document(L, 1); int i = luaL_checkint(L, 2); i = i + 1; if (i <= (*d)->countPages()) { lua_pushnumber(L, i); // new counter push_page(L, (*d)->page(i-1), false); // page return 2; } else return 0; } // returns page iterator for use in for loop // returns iterator function, invariant state, control variable static int document_pages(lua_State *L) { (void) check_document(L, 1); lua_pushcfunction(L, document_page_iterator); // iterator function lua_pushvalue(L, 1); // document lua_pushnumber(L, 0); // counter return 3; } // "export", "nozip", "markedview", "nocolor" static uint check_flags(lua_State *L, int index) { if (lua_isnoneornil(L, index)) return 0; luaL_argcheck(L, lua_istable(L, index), index, "argument is not a table"); uint flags = 0; lua_getfield(L, index, "export"); if (lua_toboolean(L, -1)) flags |= Document::EExport; lua_pop(L, 1); lua_getfield(L, index, "nozip"); if (lua_toboolean(L, -1)) flags |= Document::ENoZip; lua_pop(L, 1); lua_getfield(L, index, "markedview"); if (lua_toboolean(L, -1)) flags |= Document::EMarkedView; lua_pop(L, 1); lua_getfield(L, index, "nocolor"); if (lua_toboolean(L, -1)) flags |= Document::ENoColor; lua_pop(L, 1); return flags; } static int document_save(lua_State *L) { Document **d = check_document(L, 1); String fname = check_filename(L, 2); int format; if (lua_isnoneornil(L, 3)) format = Document::formatFromFilename(fname); else format = luaL_checkoption(L, 3, 0, format_name); uint flags = check_flags(L, 4); bool result = (*d)->save(fname.z(), Document::TFormat(format), flags); lua_pushboolean(L, result); return 1; } static int document_exportPages(lua_State *L) { Document **d = check_document(L, 1); String fname = check_filename(L, 2); uint flags = check_flags(L, 3); int fromPage = check_pageno(L, 4, *d); int toPage = check_pageno(L, 5, *d); bool result = (*d)->exportPages(fname.z(), flags, fromPage, toPage); lua_pushboolean(L, result); return 1; } static int document_exportView(lua_State *L) { Document **d = check_document(L, 1); String fname = check_filename(L, 2); int format; if (lua_isnoneornil(L, 3)) format = Document::formatFromFilename(fname); else format = luaL_checkoption(L, 3, 0, format_name); uint flags = check_flags(L, 4); int pno = check_pageno(L, 5, *d); int vno = check_viewno(L, 6, (*d)->page(pno)); bool result = (*d)->exportView(fname.z(), Document::TFormat(format), flags, pno, vno); lua_pushboolean(L, result); return 1; } // Document --> int static int document_countTotalViews(lua_State *L) { Document **d = check_document(L, 1); lua_pushinteger(L, (*d)->countTotalViews()); return 1; } // Document --> boolean static int document_has(lua_State *L) { static const char * const what_names[] = { "truetype", "gradients", "tilings", "transparency", 0 }; Document **d = check_document(L, 1); int what = luaL_checkoption(L, 2, 0, what_names); bool result = false; switch (what) { case 0: // result = (*d)->hasTrueTypeFonts(); break; case 1: result = (*d)->hasGradients(); break; case 2: result = (*d)->hasTilings(); break; case 3: result = (*d)->hasTransparency(); break; default: break; } lua_pushboolean(L, result); return 1; } static int document_sheets(lua_State *L) { Document **d = check_document(L, 1); push_cascade(L, (*d)->cascade(), false); return 1; } static int document_replaceSheets(lua_State *L) { Document **d = check_document(L, 1); SCascade *p = check_cascade(L, 2); Cascade *sheets = p->cascade; if (!p->owned) sheets = new Cascade(*p->cascade); Cascade *old = (*d)->replaceCascade(sheets); p->owned = false; // now owned by document push_cascade(L, old); return 1; } static int document_runLatex(lua_State *L) { Document **d = check_document(L, 1); String log; int result = (*d)->runLatex(log); if (result == Document::ErrNone) { lua_pushboolean(L, true); lua_pushnil(L); lua_pushnil(L); } else if (result == Document::ErrNoText) { lua_pushboolean(L, true); lua_pushnil(L); lua_pushliteral(L, "notext"); } else { lua_pushboolean(L, false); switch (result) { case Document::ErrNoDir: lua_pushliteral(L, "Directory does not exist and cannot be created"); lua_pushliteral(L, "nodir"); break; case Document::ErrWritingSource: lua_pushliteral(L, "Error writing Latex source"); lua_pushliteral(L, "writingsource"); break; case Document::ErrOldPdfLatex: lua_pushliteral(L, "Your installed version of Pdflatex is too old"); lua_pushliteral(L, "oldpdflatex"); break; case Document::ErrRunLatex: lua_pushliteral(L, "There was an error trying to run Pdflatex"); lua_pushliteral(L, "runlatex"); break; case Document::ErrLatex: lua_pushliteral(L, "There were Latex errors"); lua_pushliteral(L, "latex"); break; case Document::ErrLatexOutput: lua_pushliteral(L, "There was an error reading the Pdflatex output"); lua_pushliteral(L, "latexoutput"); break; case Document::ErrNoIconv: lua_pushliteral(L, "This document needs charset conversion to run " "Pdflatex, but Ipe is compiled without this feature"); lua_pushliteral(L, "noiconv"); break; } } push_string(L, log); return 4; } static int document_checkStyle(lua_State *L) { Document **d = check_document(L, 1); AttributeSeq seq; (*d)->checkStyle(seq); lua_createtable(L, 0, seq.size()); for (uint i = 0; i < seq.size(); ++i) { push_attribute(L, seq[i]); lua_rawseti(L, -2, i+1); } return 1; } static int document_set(lua_State *L) { Document **d = check_document(L, 1); int no = check_pageno(L, 2, *d); Page *p = check_page(L, 3)->page; Page *old = (*d)->set(no, new Page(*p)); push_page(L, old); return 1; } static int document_insert(lua_State *L) { Document **d = check_document(L, 1); int no = check_pageno(L, 2, *d, 1); SPage *p = check_page(L, 3); (*d)->insert(no, new Page(*p->page)); return 0; } static int document_append(lua_State *L) { Document **d = check_document(L, 1); SPage *p = check_page(L, 2); (*d)->push_back(new Page(*p->page)); return 0; } static int document_remove(lua_State *L) { Document **d = check_document(L, 1); int no = check_pageno(L, 2, *d); Page *old = (*d)->remove(no); push_page(L, old); return 1; } static int document_properties(lua_State *L) { Document **d = check_document(L, 1); Document::SProperties prop = (*d)->properties(); lua_createtable(L, 11, 0); push_string(L, prop.iTitle); lua_setfield(L, -2, "title"); push_string(L, prop.iAuthor); lua_setfield(L, -2, "author"); push_string(L, prop.iSubject); lua_setfield(L, -2, "subject"); push_string(L, prop.iKeywords); lua_setfield(L, -2, "keywords"); push_string(L, prop.iPreamble); lua_setfield(L, -2, "preamble"); push_string(L, prop.iCreated); lua_setfield(L, -2, "created"); push_string(L, prop.iModified); lua_setfield(L, -2, "modified"); push_string(L, prop.iCreator); lua_setfield(L, -2, "creator"); lua_pushboolean(L, prop.iFullScreen); lua_setfield(L, -2, "fullscreen"); lua_pushboolean(L, prop.iNumberPages); lua_setfield(L, -2, "numberpages"); return 1; } static void propFlag(lua_State *L, const char *name, bool &flag) { lua_getfield(L, 2, name); if (!lua_isnil(L, -1)) flag = lua_toboolean(L, -1); lua_pop(L, 1); } static void propString(lua_State *L, const char *name, String &str) { lua_getfield(L, 2, name); if (lua_isstring(L, -1)) str = lua_tostring(L, -1); lua_pop(L, 1); } static int document_setProperties(lua_State *L) { Document **d = check_document(L, 1); luaL_checktype(L, 2, LUA_TTABLE); Document::SProperties prop = (*d)->properties(); // take from table propFlag(L, "numberpages", prop.iNumberPages); propFlag(L, "fullscreen", prop.iFullScreen); propString(L, "title", prop.iTitle); propString(L, "author", prop.iAuthor); propString(L, "subject", prop.iSubject); propString(L, "keywords", prop.iKeywords); propString(L, "preamble", prop.iPreamble); propString(L, "created", prop.iCreated); propString(L, "modified", prop.iModified); propString(L, "creator", prop.iCreator); (*d)->setProperties(prop); return 0; } // -------------------------------------------------------------------- static const struct luaL_Reg document_methods[] = { { "__gc", document_destruct }, { "__tostring", document_tostring }, { "__len", document_len }, { "__index", document_index }, { "pages", document_pages }, { "save", document_save }, { "exportPages", document_exportPages }, { "exportView", document_exportView }, { "set", document_set }, { "insert", document_insert }, { "append", document_append }, { "remove", document_remove }, { "countTotalViews", document_countTotalViews }, { "sheets", document_sheets }, { "replaceSheets", document_replaceSheets }, { "has", document_has }, { "runLatex", document_runLatex }, { "checkStyle", document_checkStyle }, { "properties", document_properties }, { "setProperties", document_setProperties }, { NULL, NULL } }; // -------------------------------------------------------------------- static int file_format(lua_State *L) { String fname = check_filename(L, 1); FILE *fd = fopen(fname.z(), "rb"); if (!fd) luaL_error(L, "fopen error: %s", strerror(errno)); FileSource source(fd); int format = Document::fileFormat(source); fclose(fd); lua_pushstring(L, format_name[format]); return 1; } static int ipe_normalizeangle(lua_State *L) { Angle alpha(luaL_checknumber(L, 1)); double low = luaL_checknumber(L, 2); lua_pushnumber(L, double(alpha.normalize(low))); return 1; } static int ipe_splinetobeziers(lua_State *L) { luaL_argcheck(L, lua_istable(L, 1), 1, "argument is not a table"); std::vector v; int no = lua_rawlen(L, 1); for (int i = 1; i <= no; ++i) { lua_rawgeti(L, 1, i); luaL_argcheck(L, is_type(L, -1, "Ipe.vector"), 1, "element is not a vector"); Vector *u = check_vector(L, -1); v.push_back(*u); lua_pop(L, 1); } bool closed = lua_toboolean(L, 2); std::vector result; if (closed) Bezier::closedSpline(v.size(), &v[0], result); else Bezier::spline(v.size(), &v[0], result); lua_createtable(L, result.size(), 0); for (uint i = 0; i < result.size(); ++i) { lua_createtable(L, 4, 1); lua_pushliteral(L, "bezier"); lua_setfield(L, -2, "type"); for (int k = 0; k < 4; ++k) { if (k == 0 && i > 0) push_vector(L, result[i-1].iV[3]); else push_vector(L, result[i].iV[k]); lua_rawseti(L, -2, k+1); } lua_rawseti(L, -2, i+1); } return 1; } static int ipe_fileExists(lua_State *L) { String s = check_filename(L, 1); lua_pushboolean(L, Platform::fileExists(s)); return 1; } static const struct luaL_Reg ipelib_functions[] = { { "Document", document_constructor }, { "Page", page_constructor }, { "Vector", vector_constructor }, { "Direction", direction_constructor }, { "Matrix", matrix_constructor }, { "Translation", translation_constructor }, { "Rotation", rotation_constructor }, { "Rect", rect_constructor }, { "Line", line_constructor }, { "LineThrough", line_through }, { "Bisector", line_bisector }, { "Segment", segment_constructor }, { "Bezier", bezier_constructor }, { "Quad", quad_constructor }, { "Arc", arc_constructor }, { "Reference", reference_constructor }, { "Text", text_constructor }, { "Path", path_constructor }, { "Group", group_constructor }, { "Object", xml_constructor }, { "Sheet", sheet_constructor }, { "Sheets", cascade_constructor }, { "fileFormat", file_format }, { "Ipelet", ipelet_constructor }, { "normalizeAngle", ipe_normalizeangle }, { "splineToBeziers", ipe_splinetobeziers }, { "fileExists", ipe_fileExists }, { NULL, NULL } }; extern "C" int luaopen_ipe(lua_State *L) { Platform::initLib(IPELIB_VERSION); open_ipegeo(L); open_ipeobj(L); open_ipestyle(L); open_ipepage(L); open_ipelets(L); luaL_newmetatable(L, "Ipe.document"); luaL_setfuncs(L, document_methods, 0); lua_pop(L, 1); luaL_newlib(L, ipelib_functions); lua_setglobal(L, "ipe"); return 1; } // -------------------------------------------------------------------- ipe-7.1.4/src/ipelua/Makefile0000644000175000017500000000206012120621776015662 0ustar otfriedotfried# -------------------------------------------------------------------- # Makefile for Lua bindings for ipe # -------------------------------------------------------------------- OBJDIR = $(BUILDDIR)/obj/ipelua include ../common.mak TARGET = $(call dll_target,ipelua) MAKE_SYMLINKS = $(call dll_symlinks,ipelua) SONAME = $(call soname,ipelua) INSTALL_SYMLINKS = $(call install_symlinks,ipelua) CPPFLAGS += -I../include $(LUA_CFLAGS) LIBS += -L$(buildlib) -lipe $(LUA_LIBS) CXXFLAGS += $(DLL_CFLAGS) all: $(TARGET) sources = \ ipelib.cpp \ ipeluageo.cpp \ ipeluaobj.cpp \ ipeluastyle.cpp \ ipeluapage.cpp \ ipeluaipelet.cpp $(TARGET): $(objects) $(MAKE_LIBDIR) $(CXX) $(LDFLAGS) $(DLL_LDFLAGS) $(SONAME) -o $@ $^ $(LIBS) $(MAKE_SYMLINKS) clean: @-rm -f $(objects) $(TARGET) $(DEPEND) $(DEPEND): Makefile $(MAKE_DEPEND) -include $(DEPEND) install: $(TARGET) $(INSTALL_DIR) $(INSTALL_ROOT)$(IPELIBDIR) $(INSTALL_PROGRAMS) $(TARGET) $(INSTALL_ROOT)$(IPELIBDIR) $(INSTALL_SYMLINKS) # -------------------------------------------------------------------- ipe-7.1.4/src/ipelua/ipeluaobj.cpp0000644000175000017500000006223212120621776016707 0ustar otfriedotfried// -------------------------------------------------------------------- // ipeluaobj.cpp // -------------------------------------------------------------------- /* This file is part of the extensible drawing editor Ipe. Copyright (C) 1993-2013 Otfried Cheong Ipe is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. As a special exception, you have permission to link Ipe with the CGAL library and distribute executables, as long as you follow the requirements of the Gnu General Public License in regard to all of the software in the executable aside from CGAL. Ipe 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 General Public License for more details. You should have received a copy of the GNU General Public License along with Ipe; if not, you can find it at "http://www.gnu.org/copyleft/gpl.html", or write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ #include "ipelua.h" #include "ipereference.h" #include "ipegroup.h" #include "ipepath.h" #include "ipetext.h" #include "ipeimage.h" #include "ipeiml.h" using namespace ipe; using namespace ipelua; // -------------------------------------------------------------------- static const char *const type_names[] = { "group", "path", "text", "image", "reference", NULL }; static const char *const pinned_names[] = { "none", "horizontal", "vertical", "fixed", 0 }; static const char *const pathmode_names[] = { "stroked", "strokedfilled", "filled", 0 }; static const char *const transformation_names[] = { "translations", "rigid", "affine", 0 }; static const char *const horizontal_alignment_names[] = { "left", "right", "hcenter", 0 }; static const char *const vertical_alignment_names[] = { "bottom", "baseline", "top", "vcenter", 0 }; const char *const ipelua::linejoin_names[] = { "normal", "miter", "round", "bevel", 0 }; const char *const ipelua::linecap_names[] = { "normal", "butt", "round", "square", 0 }; const char *const ipelua::fillrule_names[] = { "normal", "wind", "evenodd", 0 }; // -------------------------------------------------------------------- void ipelua::push_string(lua_State *L, String str) { lua_pushlstring(L, str.data(), str.size()); } void ipelua::push_object(lua_State *L, Object *s0, bool owned) { SObject *s = (SObject *) lua_newuserdata(L, sizeof(SObject)); s->owned = owned; s->obj = s0; luaL_getmetatable(L, "Ipe.object"); lua_setmetatable(L, -2); } void ipelua::push_color(lua_State *L, Color color) { lua_createtable(L, 0, 3); lua_pushnumber(L, color.iRed.toDouble()); lua_setfield(L, -2, "r"); lua_pushnumber(L, color.iGreen.toDouble()); lua_setfield(L, -2, "g"); lua_pushnumber(L, color.iBlue.toDouble()); lua_setfield(L, -2, "b"); } void ipelua::push_attribute(lua_State *L, Attribute att) { if (att.isBoolean()) lua_pushboolean(L, att.boolean()); else if (att.isSymbolic() || att.isString() || att.isEnum()) push_string(L, att.string()); else if (att.isNumber()) lua_pushnumber(L, att.number().toDouble()); else // must be color push_color(L, att.color()); } // i must be positive Color ipelua::check_color(lua_State *L, int i) { luaL_checktype(L, i, LUA_TTABLE); lua_getfield(L, i, "r"); lua_getfield(L, i, "g"); lua_getfield(L, i, "b"); double r = luaL_checknumber(L, -3); double g = luaL_checknumber(L, -2); double b = luaL_checknumber(L, -1); lua_pop(L, 3); Color color; color.iRed = Fixed::fromDouble(r); color.iGreen = Fixed::fromDouble(g); color.iBlue = Fixed::fromDouble(b); return color; } #if 0 // i must be positive Attribute ipelua::check_attribute(lua_State *L, int i) { if (lua_type(L, i) == LUA_TNUMBER) { double v = luaL_checknumber(L, i); return Attribute(Fixed::fromInternal(int(v * 1000 + 0.5))); } else if (lua_type(L, i) == LUA_TSTRING) { const char *s = luaL_checkstring(L, i); if (!strcmp(s, "true")) return Attribute::Boolean(true); if (!strcmp(s, "false")) return Attribute::Boolean(false); if (('a' <= s[0] && s[0] <= 'z') || ('A' <= s[0] && s[0] <= 'Z')) return Attribute(true, s); else return Attribute(false, s); } else if (lua_type(L, i) == LUA_TTABLE) { Color color = check_color(L, i); return Attribute(color); } else if (lua_type(L, i) == LUA_TBOOLEAN) { return Attribute::Boolean(lua_toboolean(L, i)); } else { luaL_argerror(L, i, "attribute expected"); return Attribute::NORMAL(); // placate compiler } } #endif // i must be positive Attribute ipelua::check_color_attribute(lua_State *L, int i) { if (lua_type(L, i) == LUA_TSTRING) { const char *s = luaL_checkstring(L, i); return Attribute(true, s); } else { Color color = check_color(L, i); return Attribute(color); } } // i must be positive Attribute ipelua::check_bool_attribute(lua_State *L, int i) { static const char * const bool_names[] = { "false", "true" }; if (lua_type(L, i) == LUA_TBOOLEAN) return Attribute::Boolean(lua_toboolean(L, i)); int val = luaL_checkoption(L, i, 0, bool_names); return Attribute::Boolean(val); } // i must be positive Attribute ipelua::check_number_attribute(lua_State *L, int i) { if (lua_type(L, i) == LUA_TNUMBER) { double v = luaL_checknumber(L, i); return Attribute(Fixed::fromInternal(int(v * 1000 + 0.5))); } const char *s = luaL_checkstring(L, i); return Attribute(true, s); } Attribute ipelua::check_property(Property prop, lua_State *L, int i) { int val; switch (prop) { case EPropHorizontalAlignment: val = luaL_checkoption(L, i, 0, horizontal_alignment_names); return Attribute(THorizontalAlignment(val)); case EPropVerticalAlignment: val = luaL_checkoption(L, i, 0, vertical_alignment_names); return Attribute(TVerticalAlignment(val)); case EPropLineJoin: val = luaL_checkoption(L, i, 0, linejoin_names); return Attribute(TLineJoin(val)); case EPropLineCap: val = luaL_checkoption(L, i, 0, linecap_names); return Attribute(TLineCap(val)); case EPropFillRule: val = luaL_checkoption(L, i, 0, fillrule_names); return Attribute(TFillRule(val)); case EPropPinned: val = luaL_checkoption(L, i, 0, pinned_names); return Attribute(TPinned(val)); case EPropTransformations: val = luaL_checkoption(L, i, 0, transformation_names); return Attribute(TTransformations(val)); case EPropPathMode: val = luaL_checkoption(L, i, 0, pathmode_names); return Attribute(TPathMode(val)); case EPropPen: case EPropSymbolSize: case EPropFArrowSize: case EPropRArrowSize: case EPropTextSize: return check_number_attribute(L, i); case EPropWidth: { // absolute number only! double v = luaL_checknumber(L, i); return Attribute(Fixed::fromInternal(int(v * 1000 + 0.5))); } case EPropFArrowShape: case EPropRArrowShape: case EPropMarkShape: case EPropTextStyle: case EPropOpacity: case EPropGradient: case EPropTiling: // symbolic string only return Attribute(true, luaL_checkstring(L, i)); case EPropStrokeColor: case EPropFillColor: return check_color_attribute(L, i); case EPropDashStyle: return Attribute::makeDashStyle(luaL_checkstring(L, i)); case EPropFArrow: case EPropRArrow: case EPropMinipage: case EPropTransformableText: return check_bool_attribute(L, i); } return Attribute::NORMAL(); // placate compiler } static void get_attribute(lua_State *L, int i, Property prop, const char *key, Attribute &att) { lua_getfield(L, i, key); if (!lua_isnil(L, -1)) att = check_property(prop, L, lua_gettop(L)); // arg must be positive lua_pop(L, 1); } static void get_boolean(lua_State *L, int i, const char *key, bool &att) { lua_getfield(L, i, key); att = lua_toboolean(L, -1); lua_pop(L, 1); } static int get_option(lua_State *L, int i, const char *key, const char *const *names) { lua_getfield(L, i, key); int val; if (!lua_isnil(L, -1)) val = luaL_checkoption(L, -1, 0, names); else val = -1; lua_pop(L, 1); return val; } // i must be positive void ipelua::check_allattributes(lua_State *L, int i, AllAttributes &all) { luaL_checktype(L, i, LUA_TTABLE); get_attribute(L, i, EPropStrokeColor, "stroke", all.iStroke); get_attribute(L, i, EPropFillColor, "fill", all.iFill); get_attribute(L, i, EPropDashStyle, "dashstyle", all.iDashStyle); get_attribute(L, i, EPropPen, "pen", all.iPen); get_boolean(L, i, "farrow", all.iFArrow); get_boolean(L, i, "rarrow", all.iRArrow); get_attribute(L, i, EPropFArrowShape, "farrowshape", all.iFArrowShape); get_attribute(L, i, EPropRArrowShape, "rarrowshape", all.iRArrowShape); get_attribute(L, i, EPropFArrowSize, "farrowsize", all.iFArrowSize); get_attribute(L, i, EPropRArrowSize, "rarrowsize", all.iRArrowSize); get_attribute(L, i, EPropSymbolSize, "symbolsize", all.iSymbolSize); get_attribute(L, i, EPropMarkShape, "markshape", all.iMarkShape); get_attribute(L, i, EPropTextSize, "textsize", all.iTextSize); get_boolean(L, i, "transformabletext", all.iTransformableText); get_attribute(L, i, EPropTextStyle, "textstyle", all.iTextStyle); get_attribute(L, i, EPropOpacity, "opacity", all.iOpacity); get_attribute(L, i, EPropTiling, "tiling", all.iTiling); get_attribute(L, i, EPropGradient, "gradient", all.iGradient); int t; t = get_option(L, i, "horizontalalignment", horizontal_alignment_names); if (t >= 0) all.iHorizontalAlignment = THorizontalAlignment(t); t = get_option(L, i, "verticalalignment", vertical_alignment_names); if (t >= 0) all.iVerticalAlignment = TVerticalAlignment(t); t = get_option(L, i, "linejoin", linejoin_names); if (t >= 0) all.iLineJoin = TLineJoin(t); t = get_option(L, i, "linecap", linecap_names); if (t >= 0) all.iLineCap = TLineCap(t); t = get_option(L, i, "fillrule", fillrule_names); if (t >= 0) all.iFillRule = TFillRule(t); t = get_option(L, i, "pinned", pinned_names); if (t >= 0) all.iPinned = TPinned(t); t = get_option(L, i, "transformations", transformation_names); if (t >= 0) all.iTransformations = TTransformations(t); t = get_option(L, i, "pathmode", pathmode_names); if (t >= 0) all.iPathMode = TPathMode(t); } // -------------------------------------------------------------------- int ipelua::reference_constructor(lua_State *L) { AllAttributes all; check_allattributes(L, 1, all); Attribute name(true, luaL_checkstring(L, 2)); Vector *v = check_vector(L, 3); Reference *r = new Reference(all, name, *v); push_object(L, r); return 1; } int ipelua::text_constructor(lua_State *L) { AllAttributes all; check_allattributes(L, 1, all); const char *s = luaL_checkstring(L, 2); Vector *v = check_vector(L, 3); double width = 10.0; Text::TextType type = Text::ELabel; if (lua_isnumber(L, 4)) { type = Text::EMinipage; width = luaL_checknumber(L, 4); } Text *t = new Text(all, s, *v, type, width); push_object(L, t); return 1; } int ipelua::path_constructor(lua_State *L) { AllAttributes all; check_allattributes(L, 1, all); Shape shape = check_shape(L, 2); bool withArrows = lua_toboolean(L, 3); Path *p = new Path(all, shape, withArrows); push_object(L, p); return 1; } int ipelua::group_constructor(lua_State *L) { luaL_checktype(L, 1, LUA_TTABLE); Group *g = new Group(); // make sure Lua will collect it if exception happens push_object(L, g); int no = lua_rawlen(L, 1); for (int i = 1; i <= no; ++i) { lua_rawgeti(L, 1, i); luaL_argcheck(L, is_type(L, -1, "Ipe.object"), 1, "element is not an Ipe object"); SObject *p = (SObject *) lua_touserdata(L, -1); g->push_back(p->obj->clone()); lua_pop(L, 1); // object i } return 1; } int ipelua::xml_constructor(lua_State *L) { String s = luaL_checkstring(L, 1); Buffer buffer(s.data(), s.size()); BufferSource source(buffer); ImlParser parser(source); String tag = parser.parseToTag(); if (tag == "ipeselection") { lua_newtable(L); int index = 1; XmlAttributes attr; if (!parser.parseAttributes(attr)) return 0; tag = parser.parseToTag(); while (tag == "bitmap") { if (!parser.parseBitmap()) return false; tag = parser.parseToTag(); } for (;;) { if (tag == "/ipeselection") return 1; Object *obj = parser.parseObject(tag); if (!obj) return 0; push_object(L, obj); lua_rawseti(L, -2, index); ++index; tag = parser.parseToTag(); } } else { Object *obj = parser.parseObject(tag); if (obj) { push_object(L, obj); return 1; } } return 0; } // -------------------------------------------------------------------- static int object_destructor(lua_State *L) { SObject *r = check_object(L, 1); if (r->owned && r->obj) delete r->obj; r->obj = 0; return 0; } static int object_tostring(lua_State *L) { SObject *s = check_object(L, 1); lua_pushfstring(L, "Object(%s)@%p", type_names[s->obj->type()], lua_topointer(L, 1)); return 1; } static int object_type(lua_State *L) { SObject *s = check_object(L, 1); lua_pushstring(L, type_names[s->obj->type()]); return 1; } static int object_set(lua_State *L) { SObject *s = check_object(L, 1); Property prop = Property(luaL_checkoption(L, 2, NULL, property_names)); Attribute value = check_property(prop, L, 3); // XXX stroke and fill are no longer used Attribute stroke = Attribute::BLACK(); Attribute fill = Attribute::WHITE(); if (!lua_isnoneornil(L, 4)) stroke = check_color_attribute(L, 4); if (!lua_isnoneornil(L, 5)) fill = check_color_attribute(L, 5); s->obj->setAttribute(prop, value, stroke, fill); return 0; } static int object_get(lua_State *L) { SObject *s = check_object(L, 1); Property prop = Property(luaL_checkoption(L, 2, NULL, property_names)); Attribute value = s->obj->getAttribute(prop); push_attribute(L, value); return 1; } static int object_position(lua_State *L) { Object *obj = check_object(L, 1)->obj; luaL_argcheck(L, obj->type() == Object::EText || obj->type() == Object::EReference, 1, "not a text or reference object"); if (obj->asReference()) { push_vector(L, obj->asReference()->position()); return 1; } else if (obj->asText()) { push_vector(L, obj->asText()->position()); return 1; } return 0; } static int object_text(lua_State *L) { Object *obj = check_object(L, 1)->obj; luaL_argcheck(L, obj->type() == Object::EText, 1, "not a text object"); push_string(L, obj->asText()->text()); return 1; } static int object_setText(lua_State *L) { Object *obj = check_object(L, 1)->obj; String s = luaL_checkstring(L, 2); luaL_argcheck(L, obj->type() == Object::EText, 1, "not a text object"); obj->asText()->setText(s); return 0; } static int object_clone(lua_State *L) { SObject *s = check_object(L, 1); push_object(L, s->obj->clone()); return 1; } static int object_matrix(lua_State *L) { SObject *s = check_object(L, 1); push_matrix(L, s->obj->matrix()); return 1; } static int object_setMatrix(lua_State *L) { SObject *s = check_object(L, 1); Matrix *m = check_matrix(L, 2); s->obj->setMatrix(*m); return 0; } static int object_elements(lua_State *L) { Object *obj = check_object(L, 1)->obj; luaL_argcheck(L, obj->type() == Object::EGroup, 1, "not a group object"); Group *g = obj->asGroup(); lua_createtable(L, g->count(), 0); for (int i = 0; i < g->count(); ++i) { push_object(L, g->object(i)->clone()); lua_rawseti(L, -2, i+1); } return 1; } static int object_xml(lua_State *L) { SObject *obj = check_object(L, 1); String s; StringStream stream(s); obj->obj->saveAsXml(stream, String()); push_string(L, s); return 1; } static int object_addToBBox(lua_State *L) { SObject *s = check_object(L, 1); Rect *r = check_rect(L, 2); Matrix *m = check_matrix(L, 3); bool cp = true; if (lua_type(L, 4) == LUA_TBOOLEAN) cp = lua_toboolean(L, 4); s->obj->addToBBox(*r, *m, cp); return 0; } // -------------------------------------------------------------------- static const char * const segtype_names[] = { "arc", "segment", "quad", "bezier", "spline", 0 }; static int segtype_cp[] = { 2, 2, 3, 4, 0 }; static const char * const subpath_names[] = { "curve", "ellipse", "closedspline", 0 }; static bool collect_cp(lua_State *L, std::vector &cp) { for (int i = 0; ; ++i) { lua_rawgeti(L, -1, i+1); if (lua_isnil(L, -1)) { lua_pop(L, 1); return true; } if (!is_type(L, -1, "Ipe.vector")) return false; Vector *v = check_vector(L, -1); cp.push_back(*v); lua_pop(L, 1); // cp } } static SubPath *get_ellipse(lua_State *L, int index) { lua_rawgeti(L, -1, 1); // get matrix if (!is_type(L, -1, "Ipe.matrix")) luaL_error(L, "element %d has no matrix", index); Matrix *m = check_matrix(L, -1); lua_pop(L, 1); // matrix return new Ellipse(*m); } static SubPath *get_closedspline(lua_State *L, int index) { std::vector cp; if (!collect_cp(L, cp)) luaL_error(L, "non-vector control point in element %d", index); return new ClosedSpline(cp); } static SubPath *get_curve(lua_State *L, int index) { IpeAutoPtr c(new Curve()); lua_getfield(L, -1, "closed"); if (!lua_isboolean(L, -1)) luaL_error(L, "element %d has no 'closed' field", index); c->setClosed(lua_toboolean(L, -1)); lua_pop(L, 1); // closed for (int i = 0; ; ++i) { lua_rawgeti(L, -1, i+1); if (lua_isnil(L, -1)) { lua_pop(L, 1); if (c->countSegments() == 0) luaL_error(L, "element %d has no segments", index); return c.take(); } if (!lua_istable(L, -1)) luaL_error(L, "segment %d of element %d is not a table", i+1, index); lua_getfield(L, -1, "type"); if (!lua_isstring(L, -1)) luaL_error(L, "segment %d of element %d has no type", i+1, index); int type = test_option(L, -1, segtype_names); if (type < 0) luaL_error(L, "segment %d of element %d has invalid type", i+1, index); lua_pop(L, 1); // pop type std::vector cp; if (!collect_cp(L, cp)) luaL_error(L, "non-vector control point in segment %d of element %d", i+1, index); int cpn = segtype_cp[type]; if (int(cp.size()) < 2 || (cpn > 0 && int(cp.size()) != cpn)) luaL_error(L, "invalid # of control points in segment %d of element %d", i+1, index); switch (type) { case CurveSegment::EArc: { lua_getfield(L, -1, "arc"); if (!is_type(L, -1, "Ipe.arc")) luaL_error(L, "segment %d of element %d has no arc", i+1, index); Arc *a = check_arc(L, -1); lua_pop(L, 1); // arc c->appendArc(a->iM, cp[0], cp[1]); break; } case CurveSegment::ESegment: c->appendSegment(cp[0], cp[1]); break; case CurveSegment::EQuad: c->appendQuad(cp[0], cp[1], cp[2]); break; case CurveSegment::EBezier: c->appendBezier(cp[0], cp[1], cp[2], cp[3]); break; case CurveSegment::ESpline: c->appendSpline(cp); break; default: break; } lua_pop(L, 1); // pop segment table } } // index must be positive Shape ipelua::check_shape(lua_State *L, int index) { luaL_checktype(L, index, LUA_TTABLE); Shape shape; for (int i = 0; ; ++i) { lua_rawgeti(L, index, i+1); if (lua_isnil(L, -1)) { lua_pop(L, 1); return shape; } if (!lua_istable(L, -1)) luaL_error(L, "element %d is not a table", i+1); lua_getfield(L, -1, "type"); // stack: subpath, type if (!lua_isstring(L, -1)) luaL_error(L, "element %d has no type", i+1); int type = test_option(L, -1, subpath_names); lua_pop(L, 1); // type switch (type) { case SubPath::EEllipse: shape.appendSubPath(get_ellipse(L, i+1)); break; case SubPath::EClosedSpline: shape.appendSubPath(get_closedspline(L, i+1)); break; case SubPath::ECurve: shape.appendSubPath(get_curve(L, i+1)); break; default: luaL_error(L, "element %d has invalid type", i+1); } lua_pop(L, 1); // subpath } } static void push_segment(lua_State *L, const CurveSegment &seg) { lua_createtable(L, seg.countCP(), (seg.type() == CurveSegment::EArc ? 2 : 1)); lua_pushstring(L, segtype_names[seg.type()]); lua_setfield(L, -2, "type"); for (int i = 0; i < seg.countCP(); ++i) { push_vector(L, seg.cp(i)); lua_rawseti(L, -2, i+1); } if (seg.type() == CurveSegment::EArc) { push_arc(L, seg.arc()); lua_setfield(L, -2, "arc"); } } static void push_subpath(lua_State *L, const SubPath *sp) { switch (sp->type()) { case SubPath::EEllipse: lua_createtable(L, 1, 1); lua_pushstring(L, "ellipse"); lua_setfield(L, -2, "type"); push_matrix(L, sp->asEllipse()->matrix()); lua_rawseti(L, -2, 1); break; case SubPath::EClosedSpline: { const ClosedSpline *cs = sp->asClosedSpline(); lua_createtable(L, cs->iCP.size(), 1); lua_pushstring(L, "closedspline"); lua_setfield(L, -2, "type"); for (uint j = 0; j < cs->iCP.size(); ++j) { push_vector(L, cs->iCP[j]); lua_rawseti(L, -2, j+1); } break; } case SubPath::ECurve: { const Curve *c = sp->asCurve(); lua_createtable(L, c->countSegments(), 2); lua_pushstring(L, "curve"); lua_setfield(L, -2, "type"); lua_pushboolean(L, c->closed()); lua_setfield(L, -2, "closed"); for (int j = 0; j < c->countSegments(); ++j) { push_segment(L, c->segment(j)); lua_rawseti(L, -2, j+1); } break; } } } static void push_shape(lua_State *L, const Shape &shape) { lua_createtable(L, shape.countSubPaths(), 0); for (int i = 0; i < shape.countSubPaths(); ++i) { push_subpath(L, shape.subPath(i)); lua_rawseti(L, -2, i+1); } } static int object_shape(lua_State *L) { Object *s = check_object(L, 1)->obj; luaL_argcheck(L, s->type() == Object::EPath, 1, "not a path object"); const Shape &shape = s->asPath()->shape(); push_shape(L, shape); return 1; } static int object_setShape(lua_State *L) { Object *s = check_object(L, 1)->obj; luaL_argcheck(L, s->type() == Object::EPath, 1, "not a path object"); Shape shape = check_shape(L, 2); s->asPath()->setShape(shape); return 1; } static int object_count(lua_State *L) { Object *s = check_object(L, 1)->obj; luaL_argcheck(L, s->type() == Object::EGroup, 1, "not a group object"); lua_pushnumber(L, s->asGroup()->count()); return 1; } static int object_clip(lua_State *L) { Object *s = check_object(L, 1)->obj; luaL_argcheck(L, s->type() == Object::EGroup, 1, "not a group object"); const Shape &shape = s->asGroup()->clip(); if (shape.countSubPaths() > 0) { push_shape(L, shape); return 1; } else return 0; } static int object_setclip(lua_State *L) { Object *s = check_object(L, 1)->obj; luaL_argcheck(L, s->type() == Object::EGroup, 1, "not a group object"); if (lua_isnoneornil(L, 2)) { s->asGroup()->setClip(Shape()); } else { Shape shape = check_shape(L, 2); s->asGroup()->setClip(shape); } return 0; } static int object_symbol(lua_State *L) { Object *s = check_object(L, 1)->obj; luaL_argcheck(L, s->type() == Object::EReference, 1, "not a reference object"); push_string(L, s->asReference()->name().string()); return 1; } static int object_info(lua_State *L) { static const char * const filters[] = { "direct", "flatedecode", "dctdecode" }; static const char * const colorspaces[] = { "devicergb", "devicegray", "devicecmyk" }; Object *s = check_object(L, 1)->obj; luaL_argcheck(L, s->type() == Object::EImage, 1, "not an image object"); Bitmap bm = s->asImage()->bitmap(); lua_createtable(L, 0, 7); lua_pushstring(L, colorspaces[bm.colorSpace()]); lua_setfield(L, -2, "colorspace"); lua_pushstring(L, filters[bm.filter()]); lua_setfield(L, -2, "filter"); lua_pushnumber(L, bm.components()); lua_setfield(L, -2, "components"); lua_pushnumber(L, bm.bitsPerComponent()); lua_setfield(L, -2, "bitsPerComponent"); lua_pushnumber(L, bm.width()); lua_setfield(L, -2, "width"); lua_pushnumber(L, bm.height()); lua_setfield(L, -2, "height"); lua_pushnumber(L, bm.size()); lua_setfield(L, -2, "size"); return 1; } // -------------------------------------------------------------------- static const struct luaL_Reg object_methods[] = { { "__tostring", object_tostring }, { "__gc", object_destructor }, { "type", object_type }, { "set", object_set }, { "get", object_get }, { "xml", object_xml }, { "clone", object_clone }, { "matrix", object_matrix }, { "setMatrix", object_setMatrix }, { "addToBBox", object_addToBBox }, { "position", object_position }, { "shape", object_shape }, { "setShape", object_setShape }, { "count", object_count }, { "clip", object_clip }, { "setClip", object_setclip }, { "symbol", object_symbol }, { "info", object_info }, { "position", object_position }, { "text", object_text }, { "setText", object_setText }, { "elements", object_elements }, { NULL, NULL } }; // -------------------------------------------------------------------- int ipelua::open_ipeobj(lua_State *L) { make_metatable(L, "Ipe.object", object_methods); return 0; } // -------------------------------------------------------------------- ipe-7.1.4/src/ipelua/ipeluageo.cpp0000644000175000017500000005216312120621776016711 0ustar otfriedotfried// -------------------------------------------------------------------- // ipeluageo.cpp // -------------------------------------------------------------------- /* This file is part of the extensible drawing editor Ipe. Copyright (C) 1993-2013 Otfried Cheong Ipe is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. As a special exception, you have permission to link Ipe with the CGAL library and distribute executables, as long as you follow the requirements of the Gnu General Public License in regard to all of the software in the executable aside from CGAL. Ipe 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 General Public License for more details. You should have received a copy of the GNU General Public License along with Ipe; if not, you can find it at "http://www.gnu.org/copyleft/gpl.html", or write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ #include "ipelua.h" using namespace ipe; using namespace ipelua; // -------------------------------------------------------------------- void ipelua::push_vector(lua_State *L, const Vector &v0) { Vector *v = (Vector *) lua_newuserdata(L, sizeof(Vector)); luaL_getmetatable(L, "Ipe.vector"); lua_setmetatable(L, -2); new (v) Vector(v0); } int ipelua::vector_constructor(lua_State *L) { if (lua_gettop(L) == 0) push_vector(L, Vector::ZERO); else push_vector(L, Vector(luaL_checknumber(L, 1), luaL_checknumber(L, 2))); return 1; } int ipelua::direction_constructor(lua_State *L) { Angle alpha(luaL_checknumber(L, 1)); push_vector(L, Vector(alpha)); return 1; } static int vector_get(lua_State *L) { Vector *v = check_vector(L, 1); const char *key = lua_tostring(L, 2); if (!strcmp(key, "x")) lua_pushnumber(L, v->x); else if (!strcmp(key, "y")) lua_pushnumber(L, v->y); else if (!luaL_getmetafield(L, 1, key)) lua_pushnil(L); return 1; } static int vector_tostring(lua_State *L) { Vector *v = check_vector(L, 1); lua_pushfstring(L, "(%f, %f)", v->x, v->y); return 1; } static int vector_add(lua_State *L) { Vector *v1 = check_vector(L, 1); Vector *v2 = check_vector(L, 2); push_vector(L, *v1 + *v2); return 1; } static int vector_unm(lua_State *L) { Vector *v = check_vector(L, 1); push_vector(L, Vector(-v->x, -v->y)); return 1; } static int vector_sub(lua_State *L) { Vector *v1 = check_vector(L, 1); Vector *v2 = check_vector(L, 2); push_vector(L, *v1 - *v2); return 1; } static int vector_eq(lua_State *L) { Vector *v1 = check_vector(L, 1); Vector *v2 = check_vector(L, 2); lua_pushboolean(L, *v1 == *v2); return 1; } static int vector_dot(lua_State *L) { Vector *v1 = check_vector(L, 1); Vector *v2 = check_vector(L, 2); lua_pushnumber(L, dot(*v1, *v2)); return 1; } static int vector_mul(lua_State *L) { if (lua_type(L, 1) == LUA_TNUMBER) { double scalar = luaL_checknumber(L, 1); Vector *v = check_vector(L, 2); push_vector(L, scalar * *v); } else { Vector *v = check_vector(L, 1); double scalar = luaL_checknumber(L, 2); push_vector(L, *v * scalar); } return 1; } static int vector_len(lua_State *L) { Vector *v = check_vector(L, 1); lua_pushnumber(L, v->len()); return 1; } static int vector_sqLen(lua_State *L) { Vector *v = check_vector(L, 1); lua_pushnumber(L, v->sqLen()); return 1; } static int vector_normalized(lua_State *L) { Vector *v = check_vector(L, 1); push_vector(L, v->normalized()); return 1; } static int vector_orthogonal(lua_State *L) { Vector *v = check_vector(L, 1); push_vector(L, v->orthogonal()); return 1; } static int vector_factorize(lua_State *L) { Vector *v = check_vector(L, 1); Vector *unit = check_vector(L, 2); lua_pushnumber(L, v->factorize(*unit)); return 1; } static int vector_angle(lua_State *L) { Vector *v = check_vector(L, 1); lua_pushnumber(L, double(v->angle())); return 1; } static const struct luaL_Reg vector_methods[] = { { "__index", vector_get }, { "__tostring", vector_tostring }, { "__add", vector_add }, { "__unm", vector_unm }, { "__sub", vector_sub }, { "__eq", vector_eq }, { "__mul", vector_mul }, { "__concat", vector_dot }, { "len", vector_len }, { "sqLen", vector_sqLen }, { "normalized", vector_normalized }, { "orthogonal", vector_orthogonal }, { "factorize", vector_factorize }, { "angle", vector_angle }, { NULL, NULL } }; // -------------------------------------------------------------------- void ipelua::push_matrix(lua_State *L, const Matrix &m0) { Matrix *m = (Matrix *) lua_newuserdata(L, sizeof(Matrix)); luaL_getmetatable(L, "Ipe.matrix"); lua_setmetatable(L, -2); new (m) Matrix(m0); } int ipelua::matrix_constructor(lua_State *L) { int top = lua_gettop(L); if (top == 0) push_matrix(L, Matrix()); else if (top == 4 || top == 6) { double a[6]; a[4] = a[5] = 0.0; for (int i = 0; i < top; ++i) a[i] = luaL_checknumber(L, i+1); push_matrix(L, Matrix(a[0], a[1], a[2], a[3], a[4], a[5])); } else if (top == 1 && lua_type(L, 1) == LUA_TTABLE) { double a[6]; for (int i = 0; i < 6; ++i) { lua_rawgeti(L, 1, i+1); a[i] = luaL_checknumber(L, -1); lua_pop(L, 1); } push_matrix(L, Matrix(a[0], a[1], a[2], a[3], a[4], a[5])); } else luaL_error(L, "incorrect arguments for constructor"); return 1; } int ipelua::rotation_constructor(lua_State *L) { double alpha = luaL_checknumber(L, 1); push_matrix(L, Matrix(Linear(Angle(alpha)))); return 1; } int ipelua::translation_constructor(lua_State *L) { if (lua_gettop(L) == 1) { Vector *v = check_vector(L, 1); push_matrix(L, Matrix(*v)); } else { double x = luaL_checknumber(L, 1); double y = luaL_checknumber(L, 2); push_matrix(L, Matrix(Vector(x, y))); } return 1; } static int matrix_tostring(lua_State *L) { Matrix *m = check_matrix(L, 1); lua_pushfstring(L, "[%f %f %f %f %f %f]", m->a[0], m->a[1], m->a[2], m->a[3], m->a[4], m->a[5]); return 1; } static int matrix_eq(lua_State *L) { Matrix *m1 = check_matrix(L, 1); Matrix *m2 = check_matrix(L, 2); lua_pushboolean(L, *m1 == *m2); return 1; } static int matrix_coeff(lua_State *L) { Matrix *m = check_matrix(L, 1); lua_newtable(L); for (int i = 0; i < 6; ++i) { lua_pushnumber(L, m->a[i]); lua_rawseti(L, -2, i+1); } return 1; } static int matrix_isIdentity(lua_State *L) { Matrix *m = check_matrix(L, 1); lua_pushboolean(L, m->isIdentity()); return 1; } static int matrix_isSingular(lua_State *L) { Matrix *m = check_matrix(L, 1); double t = m->a[0]*m->a[3]-m->a[1]*m->a[2]; lua_pushboolean(L, t == 0); return 1; } static int matrix_inverse(lua_State *L) { Matrix *m = check_matrix(L, 1); double t = m->a[0]*m->a[3]-m->a[1]*m->a[2]; luaL_argcheck(L, t != 0, 1, "matrix is singular"); push_matrix(L, m->inverse()); return 1; } static int matrix_translation(lua_State *L) { Matrix *m = check_matrix(L, 1); push_vector(L, m->translation()); return 1; } static int matrix_linear(lua_State *L) { Matrix *m = check_matrix(L, 1); push_matrix(L, Matrix(m->linear())); return 1; } static int matrix_elements(lua_State *L) { Matrix *m = check_matrix(L, 1); lua_createtable(L, 6, 0); for (int i = 0; i < 6; ++i) { lua_pushnumber(L, m->a[i]); lua_rawseti(L, -2, i+1); } return 1; } static int matrix_mul(lua_State *L) { Matrix *lhs = check_matrix(L, 1); if (is_type(L, 2, "Ipe.matrix")) { Matrix *rhs = check_matrix(L, 2); push_matrix(L, *lhs * *rhs); } else if (is_type(L, 2, "Ipe.arc")) { Arc *rhs = check_arc(L, 2); push_arc(L, *lhs * *rhs); } else { Vector *v = check_vector(L, 2); push_vector(L, *lhs * *v); } return 1; } static const struct luaL_Reg matrix_methods[] = { { "__tostring", matrix_tostring }, { "__eq", matrix_eq }, { "coeff", matrix_coeff }, { "isIdentity", matrix_isIdentity }, { "linear", matrix_linear }, { "translation", matrix_translation }, { "__mul", matrix_mul }, { "isSingular", matrix_isSingular }, { "inverse", matrix_inverse }, { "elements", matrix_elements }, { NULL, NULL } }; // -------------------------------------------------------------------- void ipelua::push_rect(lua_State *L, const Rect &r0) { Rect *r = (Rect *) lua_newuserdata(L, sizeof(Rect)); luaL_getmetatable(L, "Ipe.rect"); lua_setmetatable(L, -2); new (r) Rect(r0); } int ipelua::rect_constructor(lua_State *L) { push_rect(L, Rect()); return 1; } static int rect_tostring(lua_State *L) { Rect *r = check_rect(L, 1); lua_pushfstring(L, "Rect(%f,%f,%f,%f)", r->bottomLeft().x, r->bottomLeft().y, r->topRight().x, r->topRight().y); return 1; } static int rect_isEmpty(lua_State *L) { Rect *r = check_rect(L, 1); lua_pushboolean(L, r->isEmpty()); return 1; } static int rect_topRight(lua_State *L) { Rect *r = check_rect(L, 1); push_vector(L, r->topRight()); return 1; } static int rect_bottomLeft(lua_State *L) { Rect *r = check_rect(L, 1); push_vector(L, r->bottomLeft()); return 1; } static int rect_topLeft(lua_State *L) { Rect *r = check_rect(L, 1); push_vector(L, r->topLeft()); return 1; } static int rect_bottomRight(lua_State *L) { Rect *r = check_rect(L, 1); push_vector(L, r->bottomLeft()); return 1; } static int rect_left(lua_State *L) { Rect *r = check_rect(L, 1); lua_pushnumber(L, r->left()); return 1; } static int rect_right(lua_State *L) { Rect *r = check_rect(L, 1); lua_pushnumber(L, r->right()); return 1; } static int rect_bottom(lua_State *L) { Rect *r = check_rect(L, 1); lua_pushnumber(L, r->bottom()); return 1; } static int rect_top(lua_State *L) { Rect *r = check_rect(L, 1); lua_pushnumber(L, r->top()); return 1; } static int rect_width(lua_State *L) { Rect *r = check_rect(L, 1); lua_pushnumber(L, r->width()); return 1; } static int rect_height(lua_State *L) { Rect *r = check_rect(L, 1); lua_pushnumber(L, r->height()); return 1; } static int rect_add(lua_State *L) { Rect *r = check_rect(L, 1); if (is_type(L, 2, "Ipe.vector")) r->addPoint(*check_vector(L, 2)); else r->addRect(*check_rect(L, 2)); return 0; } static int rect_clipTo(lua_State *L) { Rect *r1 = check_rect(L, 1); Rect *r2 = check_rect(L, 2); r1->clipTo(*r2); return 0; } static int rect_contains(lua_State *L) { Rect *r = check_rect(L, 1); if (is_type(L, 2, "Ipe.vector")) lua_pushboolean(L, r->contains(*check_vector(L, 2))); else lua_pushboolean(L, r->contains(*check_rect(L, 2))); return 1; } static int rect_intersects(lua_State *L) { Rect *r1 = check_rect(L, 1); Rect *r2 = check_rect(L, 2); lua_pushboolean(L, r1->intersects(*r2)); return 1; } static const struct luaL_Reg rect_methods[] = { { "__tostring", rect_tostring }, { "isEmpty", rect_isEmpty }, { "topRight", rect_topRight }, { "bottomLeft", rect_bottomLeft }, { "topLeft", rect_topLeft }, { "bottomRight", rect_bottomRight }, { "left", rect_left }, { "right", rect_right }, { "bottom", rect_bottom }, { "top", rect_top }, { "width", rect_width }, { "height", rect_height }, { "add", rect_add }, { "clipTo", rect_clipTo }, { "contains", rect_contains }, { "intersects", rect_intersects }, { NULL, NULL } }; // -------------------------------------------------------------------- void ipelua::push_line(lua_State *L, const Line &l0) { Line *l = (Line *) lua_newuserdata(L, sizeof(Line)); luaL_getmetatable(L, "Ipe.line"); lua_setmetatable(L, -2); new (l) Line(l0); } int ipelua::line_constructor(lua_State *L) { Vector *p = check_vector(L, 1); Vector *dir = check_vector(L, 2); push_line(L, Line(*p, *dir)); return 1; } int ipelua::line_through(lua_State *L) { Vector *p = check_vector(L, 1); Vector *q = check_vector(L, 2); push_line(L, Line::through(*p, *q)); return 1; } int ipelua::line_bisector(lua_State *L) { Vector *p = check_vector(L, 1); Vector *q = check_vector(L, 2); luaL_argcheck(L, *p != *q, 2, "points are not distinct"); Vector mid = 0.5 * (*p + *q); Vector dir = (*p - *q).normalized().orthogonal(); push_line(L, Line(mid, dir)); return 1; } static int line_tostring(lua_State *L) { Line *l = check_line(L, 1); lua_pushfstring(L, "Line[(%f,%f)->(%f,%f)]", l->iP.x, l->iP.y, l->dir().x, l->dir().y); return 1; } static int line_side(lua_State *L) { Line *l = check_line(L, 1); Vector *p = check_vector(L, 2); double s = l->side(*p); if (s > 0.0) lua_pushnumber(L, 1.0); else if (s < 0.0) lua_pushnumber(L, -1.0); else lua_pushnumber(L, 0.0); return 1; } static int line_point(lua_State *L) { Line *l = check_line(L, 1); push_vector(L, l->iP); return 1; } static int line_dir(lua_State *L) { Line *l = check_line(L, 1); push_vector(L, l->dir()); return 1; } static int line_normal(lua_State *L) { Line *l = check_line(L, 1); push_vector(L, l->normal()); return 1; } static int line_distance(lua_State *L) { Line *l = check_line(L, 1); Vector *v = check_vector(L, 2); lua_pushnumber(L, l->distance(*v)); return 1; } static int line_intersects(lua_State *L) { Line *l1 = check_line(L, 1); Line *l2 = check_line(L, 2); Vector pt; if (l1->intersects(*l2, pt)) push_vector(L, pt); else lua_pushnil(L); return 1; } static int line_project(lua_State *L) { Line *l = check_line(L, 1); Vector *v = check_vector(L, 2); push_vector(L, l->project(*v)); return 1; } static const struct luaL_Reg line_methods[] = { { "__tostring", line_tostring }, { "side", line_side }, { "point", line_point }, { "dir", line_dir }, { "normal", line_normal }, { "distance", line_distance }, { "intersects", line_intersects }, { "project", line_project }, { NULL, NULL } }; // -------------------------------------------------------------------- void ipelua::push_segment(lua_State *L, const Segment &s0) { Segment *s = (Segment *) lua_newuserdata(L, sizeof(Segment)); luaL_getmetatable(L, "Ipe.segment"); lua_setmetatable(L, -2); new (s) Segment(s0); } int ipelua::segment_constructor(lua_State *L) { Vector *p = check_vector(L, 1); Vector *q = check_vector(L, 2); push_segment(L, Segment(*p, *q)); return 1; } static int segment_tostring(lua_State *L) { Segment *s = check_segment(L, 1); lua_pushfstring(L, "Segment[(%f,%f)-(%f,%f)]", s->iP.x, s->iP.y, s->iQ.x, s->iQ.y); return 1; } static int segment_endpoints(lua_State *L) { Segment *s = check_segment(L, 1); push_vector(L, s->iP); push_vector(L, s->iQ); return 2; } static int segment_line(lua_State *L) { Segment *s = check_segment(L, 1); push_line(L, s->line()); return 1; } static int segment_project(lua_State *L) { Segment *s = check_segment(L, 1); Vector *v = check_vector(L, 2); Vector pt; if (s->project(*v, pt)) push_vector(L, pt); else lua_pushnil(L); return 1; } static int segment_distance(lua_State *L) { Segment *s = check_segment(L, 1); Vector *v = check_vector(L, 2); lua_pushnumber(L, s->distance(*v)); return 1; } static int segment_intersects(lua_State *L) { Segment *s = check_segment(L, 1); Vector pt; if (is_type(L, 2, "Ipe.segment")) { Segment *rhs = check_segment(L, 2); if (s->intersects(*rhs, pt)) push_vector(L, pt); else lua_pushnil(L); } else { Line *rhs = check_line(L, 2); if (s->intersects(*rhs, pt)) push_vector(L, pt); else lua_pushnil(L); } return 1; } static const struct luaL_Reg segment_methods[] = { { "__tostring", segment_tostring }, { "endpoints", segment_endpoints }, { "line", segment_line }, { "project", segment_project }, { "distance", segment_distance }, { "intersects", segment_intersects }, { NULL, NULL } }; // -------------------------------------------------------------------- void ipelua::push_bezier(lua_State *L, const Bezier &b0) { Bezier *b = (Bezier *) lua_newuserdata(L, sizeof(Bezier)); luaL_getmetatable(L, "Ipe.bezier"); lua_setmetatable(L, -2); new (b) Bezier(b0); } int ipelua::bezier_constructor(lua_State *L) { Vector *p[4]; for (int i = 0; i < 4; ++i) p[i] = check_vector(L, i + 1); push_bezier(L, Bezier(*p[0], *p[1], *p[2], *p[3])); return 1; } int ipelua::quad_constructor(lua_State *L) { Vector *p[3]; for (int i = 0; i < 3; ++i) p[i] = check_vector(L, i + 1); push_bezier(L, Bezier::quadBezier(*p[0], *p[1], *p[2])); return 1; } static int bezier_tostring(lua_State *L) { check_bezier(L, 1); lua_pushfstring(L, "Bezier@%p", lua_topointer(L, 1)); return 1; } static int bezier_controlpoints(lua_State *L) { Bezier *b = check_bezier(L, 1); for (int i = 0; i < 4; ++i) push_vector(L, b->iV[i]); return 4; } static int bezier_point(lua_State *L) { Bezier *b = check_bezier(L, 1); double t = luaL_checknumber(L, 2); push_vector(L, b->point(t)); return 1; } static int bezier_bbox(lua_State *L) { Bezier *b = check_bezier(L, 1); push_rect(L, b->bbox()); return 1; } #if 0 static int bezier_intersects(lua_State *L) { Bezier *b = check_bezier(L, 1); Vector pt; if (is_type(L, 2, "Ipe.segment")) { Segment *rhs = check_segment(L, 2); if (b->intersects(*rhs, pt)) push_vector(L, pt); else lua_pushnil(L); } else { Line *rhs = check_line(L, 2); if (b->intersects(*rhs, pt)) push_vector(L, pt); else lua_pushnil(L); } return 1; } #endif static int bezier_snap(lua_State *L) { Bezier *b = check_bezier(L, 1); Vector *v = check_vector(L, 2); double t; Vector pos; double bound = 10e9; if (b->snap(*v, t, pos, bound)) { lua_pushnumber(L, t); push_vector(L, pos); return 2; } else return 0; } static const struct luaL_Reg bezier_methods[] = { { "__tostring", bezier_tostring }, { "controlpoints", bezier_controlpoints }, { "point", bezier_point }, { "bbox", bezier_bbox }, // { "intersects", bezier_intersects }, { "snap", bezier_snap }, { NULL, NULL } }; // -------------------------------------------------------------------- /* inline Arc(const Matrix &m, Angle alpha, Angle beta); Arc(const Matrix &m0, const Vector &begp, const Vector &endp); */ void ipelua::push_arc(lua_State *L, const Arc &a0) { Arc *a = (Arc *) lua_newuserdata(L, sizeof(Arc)); luaL_getmetatable(L, "Ipe.arc"); lua_setmetatable(L, -2); new (a) Arc(a0); } int ipelua::arc_constructor(lua_State *L) { Matrix *m = check_matrix(L, 1); if (lua_gettop(L) == 1) { push_arc(L, Arc(*m)); } else if (is_type(L, 2, "Ipe.vector")) { Vector *v1 = check_vector(L, 2); Vector *v2 = check_vector(L, 3); push_arc(L, Arc(*m, *v1, *v2)); } else { double alpha = luaL_checknumber(L, 2); double beta = luaL_checknumber(L, 3); push_arc(L, Arc(*m, Angle(alpha), Angle(beta))); } return 1; } static int arc_tostring(lua_State *L) { (void) check_arc(L, 1); lua_pushfstring(L, "Arc@p", lua_topointer(L, 1)); return 1; } static int arc_endpoints(lua_State *L) { Arc *b = check_arc(L, 1); push_vector(L, b->beginp()); push_vector(L, b->endp()); return 2; } static int arc_angles(lua_State *L) { Arc *b = check_arc(L, 1); lua_pushnumber(L, b->iAlpha); lua_pushnumber(L, b->iBeta); return 2; } static int arc_bbox(lua_State *L) { Arc *b = check_arc(L, 1); push_rect(L, b->bbox()); return 1; } static int arc_matrix(lua_State *L) { Arc *b = check_arc(L, 1); push_matrix(L, b->iM); return 1; } static int arc_isEllipse(lua_State *L) { Arc *b = check_arc(L, 1); lua_pushboolean(L, b->isEllipse()); return 1; } #if 0 static int arc_intersects(lua_State *L) { Arc *a = check_arc(L, 1); Vector pt; if (is_type(L, 2, "Ipe.segment")) { Segment *rhs = check_segment(L, 2); if (a->intersects(*rhs, pt)) push_vector(L, pt); else lua_pushnil(L); } else { Line *rhs = check_line(L, 2); if (a->intersects(*rhs, pt)) push_vector(L, pt); else lua_pushnil(L); } return 1; } #endif static int arc_snap(lua_State *L) { Arc *a = check_arc(L, 1); Vector *v = check_vector(L, 2); Vector pos; Angle alpha; (void) a->distance(*v, 10e9, pos, alpha); lua_pushnumber(L, double(alpha)); push_vector(L, pos); return 2; } static const struct luaL_Reg arc_methods[] = { { "__tostring", arc_tostring }, { "endpoints", arc_endpoints }, { "angles", arc_angles }, { "bbox", arc_bbox }, { "matrix", arc_matrix }, { "isEllipse", arc_isEllipse }, // { "intersects", arc_intersects }, { "snap", arc_snap }, { NULL, NULL } }; // -------------------------------------------------------------------- int ipelua::open_ipegeo(lua_State *L) { luaL_newmetatable(L, "Ipe.vector"); luaL_setfuncs(L, vector_methods, 0); lua_pop(L, 1); make_metatable(L, "Ipe.matrix", matrix_methods); make_metatable(L, "Ipe.rect", rect_methods); make_metatable(L, "Ipe.line", line_methods); make_metatable(L, "Ipe.segment", segment_methods); make_metatable(L, "Ipe.bezier", bezier_methods); make_metatable(L, "Ipe.arc", arc_methods); return 0; } // -------------------------------------------------------------------- ipe-7.1.4/src/ipelua/ipeluapage.cpp0000644000175000017500000004170012120621776017046 0ustar otfriedotfried// -------------------------------------------------------------------- // ipeluapage.cpp // -------------------------------------------------------------------- /* This file is part of the extensible drawing editor Ipe. Copyright (C) 1993-2013 Otfried Cheong Ipe is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. As a special exception, you have permission to link Ipe with the CGAL library and distribute executables, as long as you follow the requirements of the Gnu General Public License in regard to all of the software in the executable aside from CGAL. Ipe 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 General Public License for more details. You should have received a copy of the GNU General Public License along with Ipe; if not, you can find it at "http://www.gnu.org/copyleft/gpl.html", or write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ #include "ipelua.h" #include "ipepage.h" #include "ipeiml.h" using namespace ipe; using namespace ipelua; // -------------------------------------------------------------------- void ipelua::push_page(lua_State *L, Page *page, bool owned) { SPage *p = (SPage *) lua_newuserdata(L, sizeof(SPage)); p->owned = owned; luaL_getmetatable(L, "Ipe.page"); lua_setmetatable(L, -2); p->page = page; } static int check_objno(lua_State *L, int i, Page *p, int extra = 0) { int n = luaL_checkint(L, i); luaL_argcheck(L, 1 <= n && n <= p->count() + extra, i, "invalid object index"); return n - 1; } int ipelua::check_layer(lua_State *L, int i, Page *p) { const char *name = luaL_checkstring(L, i); int l = p->findLayer(name); luaL_argcheck(L, l >= 0, i, "layer does not exist"); return l; } int ipelua::check_viewno(lua_State *L, int i, Page *p, int extra) { int n = luaL_checkint(L, i); luaL_argcheck(L, 1 <= n && n <= p->countViews() + extra, i, "invalid view index"); return n - 1; } int ipelua::page_constructor(lua_State *L) { if (lua_isnoneornil(L, 1)) { push_page(L, Page::basic()); return 1; } else { size_t len; const char *p = luaL_checklstring(L, 1, &len); Buffer data(p, len); BufferSource source(data); ImlParser parser(source); Page *page = parser.parsePageSelection(); if (page) { push_page(L, page); return 1; } else return 0; } } static int page_destructor(lua_State *L) { SPage *p = check_page(L, 1); if (p->owned) delete p->page; p->page = 0; return 0; } static int page_index(lua_State *L) { Page *p = check_page(L, 1)->page; if (lua_type(L, 2) == LUA_TNUMBER) { int n = check_objno(L, 2, p); push_object(L, p->object(n), false); } else { const char *key = luaL_checkstring(L, 2); if (!luaL_getmetafield(L, 1, key)) lua_pushnil(L); } return 1; } static int page_tostring(lua_State *L) { check_page(L, 1); lua_pushfstring(L, "Page@%p", lua_topointer(L, 1)); return 1; } static int page_len(lua_State *L) { Page *p = check_page(L, 1)->page; lua_pushinteger(L, p->count()); return 1; } static int page_clone(lua_State *L) { Page *p = check_page(L, 1)->page; push_page(L, new Page(*p)); return 1; } // -------------------------------------------------------------------- static void push_select(lua_State *L, TSelect sel) { if (sel == ENotSelected) lua_pushnil(L); else if (sel == EPrimarySelected) lua_pushnumber(L, 1); else lua_pushnumber(L, 2); } static TSelect check_select(lua_State *L, int index) { TSelect w = ENotSelected; if (!lua_isnoneornil(L, index)) { if (luaL_checkint(L, index) == 1) w = EPrimarySelected; else w = ESecondarySelected; } return w; } // arguments: page, counter static int page_object_iterator(lua_State *L) { Page *p = check_page(L, 1)->page; int i = luaL_checkint(L, 2); i = i + 1; if (i <= p->count()) { lua_pushnumber(L, i); // new counter push_object(L, p->object(i-1), false); // object push_select(L, p->select(i-1)); push_string(L, p->layer(p->layerOf(i-1))); // layer return 4; } else return 0; } // returns object iterator for use in for loop // returns iterator function, invariant state, control variable static int page_objects(lua_State *L) { (void) check_page(L, 1); lua_pushcfunction(L, page_object_iterator); // iterator function lua_pushvalue(L, 1); // page lua_pushnumber(L, 0); // counter return 3; } // -------------------------------------------------------------------- static int page_xml(lua_State *L) { static const char * const option_names[] = { "ipepage", "ipeselection", 0 }; Page *p = check_page(L, 1)->page; int t = luaL_checkoption(L, 2, 0, option_names); String data; StringStream stream(data); if (t == 0) p->saveAsIpePage(stream); else if (t == 1) p->saveSelection(stream); push_string(L, data); return 1; } static int page_layers(lua_State *L) { Page *p = check_page(L, 1)->page; lua_createtable(L, 0, p->countLayers()); for (int i = 0; i < p->countLayers(); ++i) { push_string(L, p->layer(i)); lua_rawseti(L, -2, i + 1); } return 1; } static int page_countLayers(lua_State *L) { Page *p = check_page(L, 1)->page; lua_pushinteger(L, p->countLayers()); return 1; } static int page_isLocked(lua_State *L) { Page *p = check_page(L, 1)->page; int n = check_layer(L, 2, p); lua_pushboolean(L, p->isLocked(n)); return 1; } static int page_hasSnapping(lua_State *L) { Page *p = check_page(L, 1)->page; int n = check_layer(L, 2, p); lua_pushboolean(L, p->hasSnapping(n)); return 1; } static int page_setLocked(lua_State *L) { Page *p = check_page(L, 1)->page; int n = check_layer(L, 2, p); p->setLocked(n, lua_toboolean(L, 3)); return 0; } static int page_setSnapping(lua_State *L) { Page *p = check_page(L, 1)->page; int n = check_layer(L, 2, p); p->setSnapping(n, lua_toboolean(L, 3)); return 0; } static int page_renameLayer(lua_State *L) { Page *p = check_page(L, 1)->page; const char *s1 = luaL_checkstring(L, 2); const char *s2 = luaL_checkstring(L, 3); p->renameLayer(s1, s2); return 0; } static int page_addLayer(lua_State *L) { Page *p = check_page(L, 1)->page; if (lua_isnoneornil(L, 2)) { p->addLayer(); } else { const char *s = luaL_checkstring(L, 2); p->addLayer(s); } push_string(L, p->layer(p->countLayers() - 1)); return 1; } static int page_removeLayer(lua_State *L) { Page *p = check_page(L, 1)->page; int n = check_layer(L, 2, p); p->removeLayer(p->layer(n)); return 0; } static int page_moveLayer(lua_State *L) { Page *p = check_page(L, 1)->page; int index = check_layer(L, 2, p); int newIndex = luaL_checkint(L, 3) - 1; luaL_argcheck(L, 0 <= newIndex && newIndex < p->countLayers(), 3, "invalid target index"); p->moveLayer(index, newIndex); return 0; } // -------------------------------------------------------------------- static int page_select(lua_State *L) { Page *p = check_page(L, 1)->page; int n = check_objno(L, 2, p); push_select(L, p->select(n)); return 1; } static int page_setSelect(lua_State *L) { Page *p = check_page(L, 1)->page; int n = check_objno(L, 2, p); TSelect w = check_select(L, 3); p->setSelect(n, w); return 0; } static int page_layerOf(lua_State *L) { Page *p = check_page(L, 1)->page; int n = check_objno(L, 2, p); push_string(L, p->layer(p->layerOf(n))); return 1; } static int page_setLayerOf(lua_State *L) { Page *p = check_page(L, 1)->page; int n = check_objno(L, 2, p); const char *s = luaL_checkstring(L, 3); int l = p->findLayer(s); luaL_argcheck(L, l >= 0, 3, "layer does not exist"); p->setLayerOf(n, l); return 0; } static int page_bbox(lua_State *L) { Page *p = check_page(L, 1)->page; int n = check_objno(L, 2, p); push_rect(L, p->bbox(n)); return 1; } // use index nil to append static int page_insert(lua_State *L) { Page *p = check_page(L, 1)->page; int n; if (lua_isnil(L, 2)) n = p->count(); else n = check_objno(L, 2, p, 1); SObject *obj = check_object(L, 3); TSelect select = check_select(L, 4); int l = check_layer(L, 5, p); p->insert(n, select, l, obj->obj->clone()); return 0; } static int page_remove(lua_State *L) { Page *p = check_page(L, 1)->page; int n = check_objno(L, 2, p); p->remove(n); return 0; } static int page_replace(lua_State *L) { Page *p = check_page(L, 1)->page; int n = check_objno(L, 2, p); SObject *obj = check_object(L, 3); p->replace(n, obj->obj->clone()); return 0; } static int page_invalidateBBox(lua_State *L) { Page *p = check_page(L, 1)->page; int n = check_objno(L, 2, p); p->invalidateBBox(n); return 0; } static int page_transform(lua_State *L) { Page *p = check_page(L, 1)->page; int n = check_objno(L, 2, p); Matrix *m = check_matrix(L, 3); p->transform(n, *m); return 0; } static int page_distance(lua_State *L) { Page *p = check_page(L, 1)->page; int n = check_objno(L, 2, p); Vector *v = check_vector(L, 3); double bound = luaL_checknumber(L, 4); lua_pushnumber(L, p->distance(n, *v, bound)); return 1; } static int page_setAttribute(lua_State *L) { Page *p = check_page(L, 1)->page; int n = check_objno(L, 2, p); Property prop = Property(luaL_checkoption(L, 3, NULL, property_names)); Attribute value = check_property(prop, L, 4); Attribute stroke = Attribute::BLACK(); Attribute fill = Attribute::WHITE(); if (!lua_isnoneornil(L, 5)) stroke = check_color_attribute(L, 5); if (!lua_isnoneornil(L, 6)) fill = check_color_attribute(L, 6); lua_pushboolean(L, p->setAttribute(n, prop, value, stroke, fill)); return 1; } static int page_primarySelection(lua_State *L) { Page *p = check_page(L, 1)->page; int prim = p->primarySelection(); if (prim >= 0) { lua_pushnumber(L, prim + 1); return 1; } else return 0; } static int page_hasSelection(lua_State *L) { Page *p = check_page(L, 1)->page; lua_pushboolean(L, p->hasSelection()); return 1; } static int page_deselectAll(lua_State *L) { Page *p = check_page(L, 1)->page; p->deselectAll(); return 0; } static int page_ensurePrimarySelection(lua_State *L) { Page *p = check_page(L, 1)->page; p->ensurePrimarySelection(); return 0; } static int page_textBox(lua_State *L) { Page *p = check_page(L, 1)->page; Cascade *sheets = check_cascade(L, 2)->cascade; push_rect(L, p->textBox(sheets)); return 1; } static int page_titles(lua_State *L) { Page *p = check_page(L, 1)->page; lua_createtable(L, 3, 0); push_string(L, p->title()); lua_setfield(L, -2, "title"); if (!p->sectionUsesTitle(0)) { push_string(L, p->section(0)); lua_setfield(L, -2, "section"); } if (!p->sectionUsesTitle(1)) { push_string(L, p->section(1)); lua_setfield(L, -2, "subsection"); } return 1; } static int page_setTitles(lua_State *L) { Page *p = check_page(L, 1)->page; luaL_checktype(L, 2, LUA_TTABLE); lua_getfield(L, 2, "title"); if (lua_isstring(L, -1)) p->setTitle(lua_tostring(L, -1)); lua_getfield(L, 2, "section"); if (lua_isstring(L, -1)) p->setSection(0, false, lua_tostring(L, -1)); else p->setSection(0, true, ""); lua_getfield(L, 2, "subsection"); if (lua_isstring(L, -1)) p->setSection(1, false, lua_tostring(L, -1)); else p->setSection(1, true, ""); lua_pop(L, 3); // title, section, subsection return 0; } static int page_notes(lua_State *L) { Page *p = check_page(L, 1)->page; push_string(L, p->notes()); return 1; } static int page_setNotes(lua_State *L) { Page *p = check_page(L, 1)->page; String n = luaL_checkstring(L, 2); p->setNotes(n); return 0; } static int page_marked(lua_State *L) { Page *p = check_page(L, 1)->page; lua_pushboolean(L, p->marked()); return 1; } static int page_setMarked(lua_State *L) { Page *p = check_page(L, 1)->page; p->setMarked(lua_toboolean(L, 2)); return 0; } // -------------------------------------------------------------------- static int page_countViews(lua_State *L) { Page *p = check_page(L, 1)->page; lua_pushinteger(L, p->countViews()); return 1; } static int page_effect(lua_State *L) { Page *p = check_page(L, 1)->page; int n = check_viewno(L, 2, p); push_string(L, p->effect(n).string()); return 1; } static int page_setEffect(lua_State *L) { Page *p = check_page(L, 1)->page; int n = check_viewno(L, 2, p); const char *eff = luaL_checkstring(L, 3); p->setEffect(n, Attribute(true, eff)); return 0; } static int page_active(lua_State *L) { Page *p = check_page(L, 1)->page; int n = check_viewno(L, 2, p); push_string(L, p->active(n)); return 1; } static int page_setActive(lua_State *L) { Page *p = check_page(L, 1)->page; int n = check_viewno(L, 2, p); const char *name = luaL_checkstring(L, 3); p->setActive(n, name); return 0; } static int page_insertView(lua_State *L) { Page *p = check_page(L, 1)->page; int n = check_viewno(L, 2, p, 1); const char *name = luaL_checkstring(L, 3); p->insertView(n, name); return 0; } static int page_removeView(lua_State *L) { Page *p = check_page(L, 1)->page; int n = check_viewno(L, 2, p); p->removeView(n); return 0; } static int page_clearViews(lua_State *L) { Page *p = check_page(L, 1)->page; p->clearViews(); return 0; } static int page_markedView(lua_State *L) { Page *p = check_page(L, 1)->page; int n = check_viewno(L, 2, p); lua_pushboolean(L, p->markedView(n)); return 1; } static int page_setMarkedView(lua_State *L) { Page *p = check_page(L, 1)->page; int n = check_viewno(L, 2, p); p->setMarkedView(n, lua_toboolean(L, 3)); return 0; } // Either: view & layername // Or: view & object index static int page_visible(lua_State *L) { Page *p = check_page(L, 1)->page; int vno = check_viewno(L, 2, p); if (lua_type(L, 3) == LUA_TNUMBER) { int objno = check_objno(L, 3, p); lua_pushboolean(L, p->objectVisible(vno, objno)); } else { int l = check_layer(L, 3, p); lua_pushboolean(L, p->visible(vno, l)); } return 1; } static int page_setVisible(lua_State *L) { Page *p = check_page(L, 1)->page; int vno = check_viewno(L, 2, p); int l = check_layer(L, 3, p); bool vis = lua_toboolean(L, 4); p->setVisible(vno, p->layer(l), vis); return 0; } // -------------------------------------------------------------------- static int page_findedge(lua_State *L) { Page *p = check_page(L, 1)->page; Vector pos = *check_vector(L, 2); Snap snap; if (!snap.setEdge(pos, p)) return 0; push_vector(L, snap.iOrigin); lua_pushnumber(L, snap.iDir); return 2; } // -------------------------------------------------------------------- static const struct luaL_Reg page_methods[] = { { "__index", page_index }, { "__tostring", page_tostring }, { "__gc", page_destructor }, { "__len", page_len }, { "clone", page_clone }, { "objects", page_objects }, { "countViews", page_countViews }, { "countLayers", page_countLayers }, { "xml", page_xml }, { "layers", page_layers }, { "isLocked", page_isLocked }, { "hasSnapping", page_hasSnapping }, { "setLocked", page_setLocked }, { "setSnapping", page_setSnapping }, { "renameLayer", page_renameLayer }, { "addLayer", page_addLayer }, { "removeLayer", page_removeLayer }, { "moveLayer", page_moveLayer }, { "select", page_select }, { "setSelect", page_setSelect }, { "layerOf", page_layerOf }, { "setLayerOf", page_setLayerOf }, { "effect", page_effect }, { "setEffect", page_setEffect }, { "active", page_active }, { "setActive", page_setActive }, { "insertView", page_insertView }, { "removeView", page_removeView }, { "clearViews", page_clearViews }, { "markedView", page_markedView }, { "setMarkedView", page_setMarkedView }, { "visible", page_visible }, { "setVisible", page_setVisible }, { "bbox", page_bbox }, { "insert", page_insert }, { "remove", page_remove }, { "replace", page_replace }, { "invalidateBBox", page_invalidateBBox }, { "transform", page_transform }, { "distance", page_distance }, { "setAttribute", page_setAttribute }, { "primarySelection", page_primarySelection }, { "hasSelection", page_hasSelection }, { "deselectAll", page_deselectAll }, { "ensurePrimarySelection", page_ensurePrimarySelection }, { "findEdge", page_findedge }, { "titles", page_titles }, { "setTitles", page_setTitles }, { "notes", page_notes }, { "setNotes", page_setNotes }, { "marked", page_marked }, { "setMarked", page_setMarked }, { "textBox", page_textBox }, { 0, 0 } }; // -------------------------------------------------------------------- int ipelua::open_ipepage(lua_State *L) { luaL_newmetatable(L, "Ipe.page"); luaL_setfuncs(L, page_methods, 0); lua_pop(L, 1); return 0; } // -------------------------------------------------------------------- ipe-7.1.4/src/ipelua/ipeluastyle.cpp0000644000175000017500000002643412120621776017301 0ustar otfriedotfried// -------------------------------------------------------------------- // ipeluastyle.cpp // -------------------------------------------------------------------- /* This file is part of the extensible drawing editor Ipe. Copyright (C) 1993-2013 Otfried Cheong Ipe is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. As a special exception, you have permission to link Ipe with the CGAL library and distribute executables, as long as you follow the requirements of the Gnu General Public License in regard to all of the software in the executable aside from CGAL. Ipe 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 General Public License for more details. You should have received a copy of the GNU General Public License along with Ipe; if not, you can find it at "http://www.gnu.org/copyleft/gpl.html", or write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ #include "ipelua.h" #include "ipestyle.h" #include "ipeiml.h" #include using namespace ipe; using namespace ipelua; // -------------------------------------------------------------------- static const char * const set_names[] = { "preamble", "linecap", "linejoin", "fillrule", "symbol", "layout", 0 }; int ipelua::test_option(lua_State *L, int i, const char * const *names) { const char *s = lua_tostring(L, i); const char * const *p = names; int what = 0; while (*p) { if (!strcmp(s, *p)) return what; ++what; ++p; } return -1; } // -------------------------------------------------------------------- void ipelua::push_sheet(lua_State *L, StyleSheet *s0, bool owned) { SSheet *s = (SSheet *) lua_newuserdata(L, sizeof(SSheet)); s->owned = owned; s->sheet = s0; luaL_getmetatable(L, "Ipe.sheet"); lua_setmetatable(L, -2); } int ipelua::sheet_constructor(lua_State *L) { if (lua_type(L, 1) == LUA_TSTRING) { String fname = check_filename(L, 1); FILE *fd = fopen(fname.z(), "rb"); if (!fd) { lua_pushnil(L); lua_pushfstring(L, "fopen error: %s", strerror(errno)); return 2; } FileSource source(fd); ImlParser parser(source); StyleSheet *sheet = parser.parseStyleSheet(); fclose(fd); if (!sheet) { lua_pushnil(L); lua_pushfstring(L, "Parsing error at %d", parser.parsePosition()); return 2; } push_sheet(L, sheet); } else push_sheet(L, new StyleSheet()); return 1; } static int sheet_clone(lua_State *L) { SSheet *p = check_sheet(L, 1); push_sheet(L, new StyleSheet(*p->sheet)); return 1; } static int sheet_destructor(lua_State *L) { SSheet *s = check_sheet(L, 1); if (s->owned) delete s->sheet; s->sheet = 0; return 0; } static int sheet_tostring(lua_State *L) { check_sheet(L, 1); lua_pushfstring(L, "Sheet@%p", lua_topointer(L, 1)); return 1; } // -------------------------------------------------------------------- // i must be positive static Attribute check_absolute_attribute(Kind kind, lua_State *L, int i) { switch (kind) { case EPen: case ESymbolSize: case EArrowSize: case ETextSize: case ETextStretch: case EOpacity: case EGridSize: case EAngleSize: { double v = luaL_checknumber(L, i); return Attribute(Fixed::fromInternal(int(v * 1000 + 0.5))); } case EColor: { Color color = check_color(L, i); return Attribute(color); } case EDashStyle: { const char *s = luaL_checkstring(L, i); Attribute ds = Attribute::makeDashStyle(s); luaL_argcheck(L, !ds.isSymbolic(), i, "dashstyle is not absolute"); return ds; } case ETextStyle: case EEffect: case ETiling: case EGradient: case ESymbol: luaL_argerror(L, i, "cannot set absolute value of this kind"); break; } return Attribute::NORMAL(); // placate compiler } static int sheet_add(lua_State *L) { StyleSheet *s = check_sheet(L, 1)->sheet; const char *what = luaL_checkstring(L, 2); if (!strcmp(what, "symbol")) { const char *name = luaL_checkstring(L, 3); SObject *obj = check_object(L, 4); Symbol symbol; symbol.iObject = obj->obj->clone(); symbol.iTransformations = ETransformationsAffine; s->addSymbol(Attribute(true, name), symbol); } else { Kind kind = Kind(luaL_checkoption(L, 2, NULL, kind_names)); const char *name = luaL_checkstring(L, 3); Attribute sym(true, String(name)); Attribute value = check_absolute_attribute(kind, L, 4); s->add(kind, sym, value); } return 0; } static int sheet_isStandard(lua_State *L) { SSheet *p = check_sheet(L, 1); lua_pushboolean(L, p->sheet->isStandard()); return 1; } static int sheet_name(lua_State *L) { SSheet *p = check_sheet(L, 1); String n = p->sheet->name(); if (n.empty()) lua_pushnil(L); else push_string(L, n); return 1; } static int sheet_xml(lua_State *L) { SSheet *p = check_sheet(L, 1); bool with_bitmaps = lua_toboolean(L, 2); String data; StringStream stream(data); p->sheet->saveAsXml(stream, with_bitmaps); push_string(L, data); return 1; } static int sheet_setName(lua_State *L) { SSheet *p = check_sheet(L, 1); const char *name = luaL_checkstring(L, 2); p->sheet->setName(name); return 0; } static int sheet_set(lua_State *L) { StyleSheet *s = check_sheet(L, 1)->sheet; int what = luaL_checkoption(L, 2, 0, set_names); switch (what) { case 0: // preamble s->setPreamble(luaL_checkstring(L, 3)); break; case 1: // linecap s->setLineCap(check_property(EPropLineCap, L, 3).lineCap()); break; case 2: // linejoin s->setLineJoin(check_property(EPropLineJoin, L, 3).lineJoin()); break; case 3: // fillrule s->setFillRule(check_property(EPropFillRule, L, 3).fillRule()); break; default: luaL_argerror(L, 2, "invalid kind for 'set'"); break; } return 0; } // -------------------------------------------------------------------- static const struct luaL_Reg sheet_methods[] = { { "__gc", sheet_destructor }, { "__tostring", sheet_tostring }, { "clone", sheet_clone }, { "xml", sheet_xml }, { "add", sheet_add }, { "set", sheet_set }, { "isStandard", sheet_isStandard }, { "name", sheet_name }, { "setName", sheet_setName }, { NULL, NULL } }; // -------------------------------------------------------------------- void ipelua::push_cascade(lua_State *L, Cascade *s0, bool owned) { SCascade *s = (SCascade *) lua_newuserdata(L, sizeof(SCascade)); s->owned = owned; s->cascade = s0; luaL_getmetatable(L, "Ipe.cascade"); lua_setmetatable(L, -2); } int ipelua::cascade_constructor(lua_State *L) { push_cascade(L, new Cascade()); return 1; } static int cascade_clone(lua_State *L) { SCascade *s = check_cascade(L, 1); push_cascade(L, new Cascade(*s->cascade)); return 1; } static int cascade_destructor(lua_State *L) { SCascade *s = check_cascade(L, 1); if (s->owned) delete s->cascade; s->cascade = 0; return 0; } static int cascade_tostring(lua_State *L) { check_cascade(L, 1); lua_pushfstring(L, "Cascade@%p", lua_topointer(L, 1)); return 1; } // -------------------------------------------------------------------- // also works for symbol, gradient, tiling static int cascade_allNames(lua_State *L) { SCascade *p = check_cascade(L, 1); Kind kind = Kind(luaL_checkoption (L, 2, NULL, kind_names)); AttributeSeq seq; p->cascade->allNames(kind, seq); lua_createtable(L, seq.size(), 0); for (uint i = 0; i < seq.size(); ++i) { push_string(L, seq[i].string()); lua_rawseti(L, -2, i + 1); } return 1; } static int push_layout(lua_State *L, const Layout &l) { lua_createtable(L, 0, 7); push_vector(L, l.iPaperSize); lua_setfield(L, -2, "papersize"); push_vector(L, l.iOrigin); lua_setfield(L, -2, "origin"); push_vector(L, l.iFrameSize); lua_setfield(L, -2, "framesize"); lua_pushnumber(L, l.iParagraphSkip); lua_setfield(L, -2, "paragraph_skip"); lua_pushboolean(L, l.iCrop); lua_setfield(L, -2, "crop"); return 1; } // find will also work for the values that are "set" static int cascade_find(lua_State *L) { Cascade *s = check_cascade(L, 1)->cascade; luaL_checktype(L, 2, LUA_TSTRING); int what = test_option(L, 2, set_names); switch (what) { case 0: // preamble push_string(L, s->findPreamble()); break; case 1: // linecap push_attribute(L, Attribute(s->lineCap())); break; case 2: // linejoin push_attribute(L, Attribute(s->lineJoin())); break; case 3: // fillrule push_attribute(L, Attribute(s->fillRule())); break; case 4: { // symbol const char *name = luaL_checkstring(L, 3); const Symbol *symbol = s->findSymbol(Attribute(true, name)); if (symbol) push_object(L, symbol->iObject->clone()); else lua_pushnil(L); break; } case 5: // layout push_layout(L, *s->findLayout()); break; default: { Kind kind = Kind(luaL_checkoption(L, 2, NULL, kind_names)); const char *name = luaL_checkstring(L, 3); push_attribute(L, s->find(kind, Attribute(true, String(name)))); break; } } return 1; } static int cascade_has(lua_State *L) { Cascade *p = check_cascade(L, 1)->cascade; Kind kind = Kind(luaL_checkoption(L, 2, NULL, kind_names)); const char *name = luaL_checkstring(L, 3); Attribute sym(true, String(name)); lua_pushboolean(L, p->has(kind, sym)); return 1; } static int cascade_count(lua_State *L) { Cascade *p = check_cascade(L, 1)->cascade; lua_pushnumber(L, p->count()); return 1; } static int cascade_sheet(lua_State *L) { Cascade *p = check_cascade(L, 1)->cascade; int index = luaL_checkint(L, 2); luaL_argcheck(L, 1 <= index && index <= p->count(), 2, "index out of bounds"); push_sheet(L, p->sheet(index - 1), false); return 1; } static int cascade_insert(lua_State *L) { Cascade *p = check_cascade(L, 1)->cascade; int index = luaL_checkint(L, 2); luaL_argcheck(L, 1 <= index && index <= p->count() + 1, 2, "index out of bounds"); SSheet *s = check_sheet(L, 3); StyleSheet *sheet = s->sheet; if (!s->owned) sheet = new StyleSheet(*s->sheet); p->insert(index - 1, sheet); s->owned = false; // now owned by cascade return 0; } static int cascade_remove(lua_State *L) { Cascade *p = check_cascade(L, 1)->cascade; int index = luaL_checkint(L, 2); luaL_argcheck(L, 1 <= index && index <= p->count(), 2, "index out of bounds"); p->remove(index - 1); return 0; } // -------------------------------------------------------------------- static const struct luaL_Reg cascade_methods[] = { { "__gc", cascade_destructor }, { "__tostring", cascade_tostring }, { "clone", cascade_clone }, { "allNames", cascade_allNames }, { "find", cascade_find }, { "has", cascade_has }, { "count", cascade_count }, { "sheet", cascade_sheet }, { "insert", cascade_insert }, { "remove", cascade_remove }, { NULL, NULL } }; // -------------------------------------------------------------------- int ipelua::open_ipestyle(lua_State *L) { make_metatable(L, "Ipe.sheet", sheet_methods); make_metatable(L, "Ipe.cascade", cascade_methods); return 0; } // -------------------------------------------------------------------- ipe-7.1.4/src/ipescript/0000755000175000017500000000000012120621776014747 5ustar otfriedotfriedipe-7.1.4/src/ipescript/Makefile0000644000175000017500000000170212120621776016407 0ustar otfriedotfried# -------------------------------------------------------------------- # Makefile for Ipescript # -------------------------------------------------------------------- OBJDIR = $(BUILDDIR)/obj/ipescript include ../common.mak TARGET = $(call exe_target,ipescript) CPPFLAGS += -I../include -I../ipelua $(LUA_CFLAGS) LIBS += -L$(buildlib) -lipelua -lipe $(LUA_LIBS) CPPFLAGS += -DIPELETDIR=\"$(IPELETDIR)\" CPPFLAGS += -DIPESTYLEDIR=\"$(IPESTYLEDIR)\" CPPFLAGS += -DIPESCRIPTDIR=\"$(IPESCRIPTDIR)\" all: $(TARGET) sources = ipescript.cpp lfs.cpp $(TARGET): $(objects) $(MAKE_BINDIR) $(CXX) $(LDFLAGS) -o $@ $^ $(LIBS) clean: @-rm -f $(objects) $(TARGET) $(DEPEND) $(DEPEND): Makefile $(MAKE_DEPEND) -include $(DEPEND) install: $(TARGET) $(INSTALL_DIR) $(INSTALL_ROOT)$(IPEBINDIR) $(INSTALL_PROGRAMS) $(TARGET) $(INSTALL_ROOT)$(IPEBINDIR) # -------------------------------------------------------------------- ipe-7.1.4/src/ipescript/ipescript.cpp0000644000175000017500000001163712120621776017465 0ustar otfriedotfried// -------------------------------------------------------------------- // ipescript.cpp // -------------------------------------------------------------------- /* This file is part of the extensible drawing editor Ipe. Copyright (C) 1993-2013 Otfried Cheong Ipe is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. As a special exception, you have permission to link Ipe with the CGAL library and distribute executables, as long as you follow the requirements of the Gnu General Public License in regard to all of the software in the executable aside from CGAL. Ipe 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 General Public License for more details. You should have received a copy of the GNU General Public License along with Ipe; if not, you can find it at "http://www.gnu.org/copyleft/gpl.html", or write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ #include "ipebase.h" #include "ipelua.h" #include #include using namespace ipe; using namespace ipelua; extern int luaopen_lfs (lua_State *L); // -------------------------------------------------------------------- static int traceback (lua_State *L) { if (!lua_isstring(L, 1)) /* 'message' not a string? */ return 1; /* keep it intact */ lua_rawgeti(L, LUA_REGISTRYINDEX, LUA_RIDX_GLOBALS); lua_getfield(L, -1, "debug"); if (!lua_istable(L, -1)) { lua_pop(L, 2); return 1; } lua_getfield(L, -1, "traceback"); if (!lua_isfunction(L, -1)) { lua_pop(L, 3); return 1; } lua_pushvalue(L, 1); // pass error message lua_pushinteger(L, 2); // skip this function and traceback lua_call(L, 2, 1); // call debug.traceback return 1; } static void setup_config(lua_State *L, const char *var, const char *conf) { #ifdef WIN32 push_string(L, Platform::ipeDir(conf)); #else lua_pushstring(L, conf); #endif lua_setfield(L, -2, var); } // -------------------------------------------------------------------- static lua_State *setup_lua() { lua_State *L = luaL_newstate(); luaL_openlibs(L); luaopen_ipe(L); luaopen_lfs(L); return L; } static void setup_globals(lua_State *L) { lua_getglobal(L, "package"); const char *pscripts = getenv("IPESCRIPTS"); if (pscripts) { String scripts(pscripts); String s; int i = 0; while (i < scripts.size()) { int j = i; while (i < scripts.size() && scripts[i] != ';' && scripts[i] != ':') i += 1; String d = scripts.substr(j, i-j); if (d == "_") d = IPESCRIPTDIR; d += "/?.lua"; if (!s.empty()) s += ";"; s += d; i += 1; } lua_pushstring(L, s.z()); } else { String s = "./?.lua;"; #ifdef WIN32 s += Platform::ipeDir("scripts/?.lua"); #else const char *home = getenv("HOME"); if (home) { s += home; s += "/.ipe/scripts/?.lua;"; } s += IPESCRIPTDIR "/?.lua"; #endif lua_pushstring(L, s.z()); } lua_setfield(L, -2, "path"); lua_newtable(L); // config table #if defined(WIN32) lua_pushliteral(L, "win"); #elif defined(__APPLE__) lua_pushliteral(L, "apple"); #else lua_pushliteral(L, "unix"); #endif lua_setfield(L, -2, "platform"); #ifdef WIN32 setup_config(L, "system_styles", "styles"); #else setup_config(L, "system_styles", IPESTYLEDIR); #endif push_string(L, Platform::latexDirectory()); lua_setfield(L, -2, "latexdir"); lua_pushfstring(L, "Ipe %d.%d.%d", IPELIB_VERSION / 10000, (IPELIB_VERSION / 100) % 100, IPELIB_VERSION % 100); lua_setfield(L, -2, "version"); lua_setglobal(L, "config"); } // -------------------------------------------------------------------- static void usage() { fprintf(stderr, "Usage: ipescript