added a translator for HPGL/2 files based on HPGS. It handles .hp2 files

This builds only with GCC 4, mostly because the code is C99 compliant only


git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@21209 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
Jérôme Duval 2007-05-22 22:32:50 +00:00
parent bdad0425c4
commit 57f13ad210
48 changed files with 53906 additions and 0 deletions

View File

@ -2,6 +2,7 @@ SubDir HAIKU_TOP src add-ons translators ;
SubInclude HAIKU_TOP src add-ons translators bmp ;
SubInclude HAIKU_TOP src add-ons translators gif ;
SubInclude HAIKU_TOP src add-ons translators hpgs ;
SubInclude HAIKU_TOP src add-ons translators ico ;
SubInclude HAIKU_TOP src add-ons translators jpeg ;
SubInclude HAIKU_TOP src add-ons translators jpeg2000 ;

View File

@ -0,0 +1,67 @@
/*
* Copyright 2007, Jérôme Duval. All rights reserved.
* Copyright 2005-2007, Axel Dörfler, axeld@pinc-software.de. All rights reserved.
* Distributed under the terms of the MIT License.
*/
#include "ConfigView.h"
#include "HPGSTranslator.h"
#include <StringView.h>
#include <CheckBox.h>
#include <stdio.h>
#include <string.h>
ConfigView::ConfigView(const BRect &frame, uint32 resize, uint32 flags)
: BView(frame, "HPGSTranslator Settings", resize, flags)
{
SetViewColor(ui_color(B_PANEL_BACKGROUND_COLOR));
font_height fontHeight;
be_bold_font->GetHeight(&fontHeight);
float height = fontHeight.descent + fontHeight.ascent + fontHeight.leading;
BRect rect(10, 10, 200, 10 + height);
BStringView *stringView = new BStringView(rect, "title", "HPGS Images");
stringView->SetFont(be_bold_font);
stringView->ResizeToPreferred();
AddChild(stringView);
rect.OffsetBy(0, height + 10);
char version[256];
sprintf(version, "Version %d.%d.%d, %s",
int(B_TRANSLATION_MAJOR_VERSION(HPGS_TRANSLATOR_VERSION)),
int(B_TRANSLATION_MINOR_VERSION(HPGS_TRANSLATOR_VERSION)),
int(B_TRANSLATION_REVISION_VERSION(HPGS_TRANSLATOR_VERSION)),
__DATE__);
stringView = new BStringView(rect, "version", version);
stringView->ResizeToPreferred();
AddChild(stringView);
GetFontHeight(&fontHeight);
height = fontHeight.descent + fontHeight.ascent + fontHeight.leading;
rect.OffsetBy(0, height + 5);
stringView = new BStringView(rect, "copyright", B_UTF8_COPYRIGHT "2007 Haiku Inc.");
stringView->ResizeToPreferred();
AddChild(stringView);
rect.OffsetBy(0, height + 10);
stringView = new BStringView(rect, "copyright2", "Based on HPGS (http://hpgs.berlios.de)");
stringView->ResizeToPreferred();
AddChild(stringView);
rect.OffsetBy(0, height + 5);
stringView = new BStringView(rect, "copyright3", B_UTF8_COPYRIGHT "2004-2006 ev-i Informationstechnologie GmbH");
stringView->ResizeToPreferred();
AddChild(stringView);
}
ConfigView::~ConfigView()
{
}

View File

@ -0,0 +1,19 @@
/*
* Copyright 2004-2007, Axel Dörfler, axeld@pinc-software.de. All rights reserved.
* Distributed under the terms of the MIT License.
*/
#ifndef CONFIG_VIEW_H
#define CONFIG_VIEW_H
#include <View.h>
class ConfigView : public BView {
public:
ConfigView(const BRect &frame, uint32 resize = B_FOLLOW_ALL,
uint32 flags = B_WILL_DRAW);
virtual ~ConfigView();
};
#endif /* CONFIG_VIEW_H */

View File

@ -0,0 +1,277 @@
/*
* Copyright 2007, Jérôme Duval. All rights reserved.
* Distributed under the terms of the MIT License.
*/
#include "HPGSTranslator.h"
#include "ConfigView.h"
#include "ReadHelper.h"
#include "hpgsimage.h"
#include <Messenger.h>
#include <TranslatorRoster.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
typedef struct my_hpgs_png_image_st {
hpgs_png_image image;
BPositionIO *target;
} my_hpgs_png_image;
int
my_pim_write(hpgs_image *_this, const char *filename)
{
BPositionIO* target = ((my_hpgs_png_image *)_this)->target;
unsigned char *row;
int stride, depth;
_this->vtable->get_data(_this, &row, &stride, &depth);
for (int i = 0; i< _this->height; ++i) {
ssize_t bytesWritten = target->Write(row, stride);
if (bytesWritten < B_OK)
return bytesWritten;
row += stride;
}
return 0;
}
// The input formats that this translator supports.
translation_format sInputFormats[] = {
{
HPGS_IMAGE_FORMAT,
B_TRANSLATOR_BITMAP,
HPGS_IN_QUALITY,
HPGS_IN_CAPABILITY,
"vector/x-hpgl2",
"HP-GL/2"
},
};
// The output formats that this translator supports.
translation_format sOutputFormats[] = {
{
B_TRANSLATOR_BITMAP,
B_TRANSLATOR_BITMAP,
BITS_OUT_QUALITY,
BITS_OUT_CAPABILITY,
"x-be-bitmap",
"Be Bitmap image"
},
};
// Default settings for the Translator
static TranSetting sDefaultSettings[] = {
{B_TRANSLATOR_EXT_HEADER_ONLY, TRAN_SETTING_BOOL, false},
{B_TRANSLATOR_EXT_DATA_ONLY, TRAN_SETTING_BOOL, false}
};
const uint32 kNumInputFormats = sizeof(sInputFormats) / sizeof(translation_format);
const uint32 kNumOutputFormats = sizeof(sOutputFormats) / sizeof(translation_format);
const uint32 kNumDefaultSettings = sizeof(sDefaultSettings) / sizeof(TranSetting);
// #pragma mark -
HPGSTranslator::HPGSTranslator()
: BaseTranslator("HPGS Images", "HPGS Image Translator",
HPGS_TRANSLATOR_VERSION,
sInputFormats, kNumInputFormats,
sOutputFormats, kNumOutputFormats,
"HPGSTranslator_Settings",
sDefaultSettings, kNumDefaultSettings,
B_TRANSLATOR_BITMAP, HPGS_IMAGE_FORMAT)
{
hpgs_init("/usr/local");
}
HPGSTranslator::~HPGSTranslator()
{
hpgs_cleanup();
}
status_t
HPGSTranslator::DerivedIdentify(BPositionIO *stream,
const translation_format *format, BMessage *settings,
translator_info *info, uint32 outType)
{
if (!outType)
outType = B_TRANSLATOR_BITMAP;
if (outType != B_TRANSLATOR_BITMAP)
return B_NO_TRANSLATOR;
hpgs_istream *istream = hpgs_new_wrapper_istream(stream);
status_t err = B_OK;
int verbosity = 1;
hpgs_bool multipage = HPGS_FALSE;
hpgs_bool ignore_ps = HPGS_FALSE;
hpgs_bool do_linewidth = HPGS_TRUE;
hpgs_device *size_dev = (hpgs_device *)hpgs_new_plotsize_device(ignore_ps, do_linewidth);
hpgs_reader *reader = hpgs_new_reader(istream, size_dev, multipage, verbosity);
if (hpgs_read(reader, HPGS_FALSE) == B_OK) {
info->type = HPGS_IMAGE_FORMAT;
info->group = B_TRANSLATOR_BITMAP;
info->quality = HPGS_IN_QUALITY;
info->capability = HPGS_IN_CAPABILITY;
snprintf(info->name, sizeof(info->name), "HPGS image");
strcpy(info->MIME, "vector/x-hpgl2");
} else
err = B_NO_TRANSLATOR;
free(reader);
free(size_dev);
free(istream->stream);
free(istream);
return err;
}
status_t
HPGSTranslator::DerivedTranslate(BPositionIO* source,
const translator_info* info, BMessage* settings,
uint32 outType, BPositionIO* target, int32 baseType)
{
if (!outType)
outType = B_TRANSLATOR_BITMAP;
if (outType != B_TRANSLATOR_BITMAP || baseType != 0)
return B_NO_TRANSLATOR;
status_t err = B_OK;
hpgs_istream *istream = hpgs_new_wrapper_istream(source);
TranslatorBitmap header;
ssize_t bytesWritten;
uint32 dataSize;
double paper_angle = 180.0;
double paper_border = 0.0;
double paper_width = 0.0;
double paper_height = 0.0;
int verbosity = 0;
int depth = 32;
int palette = 0;
hpgs_bool multipage = HPGS_FALSE;
hpgs_bool ignore_ps = HPGS_FALSE;
hpgs_bool do_linewidth = HPGS_TRUE;
hpgs_bool do_rop3 = HPGS_TRUE;
hpgs_bool antialias = HPGS_FALSE;
int image_interpolation = 0;
double thin_alpha = 0.25;
hpgs_device *size_dev = 0;
hpgs_bbox bbox = { 0.0, 0.0, 0.0, 0.0 };
hpgs_image *image;
hpgs_paint_device *pdv;
hpgs_device *plot_dev;
size_dev = (hpgs_device *)hpgs_new_plotsize_device(ignore_ps, do_linewidth);
hpgs_reader *reader = hpgs_new_reader(istream, size_dev, multipage, verbosity);
if (hpgs_read(reader, HPGS_FALSE)) {
fprintf(stderr, "no hpgs\n");
err = B_NO_TRANSLATOR;
goto err1;
}
if (hpgs_getplotsize(size_dev,1,&bbox)<0) {
fprintf(stderr, "no hpgs\n");
err = B_NO_TRANSLATOR;
goto err1;
}
// set the appropriate page placement.
if (paper_width > 0.0 && paper_height > 0.0) {
hpgs_reader_set_fixed_page(reader,&bbox,
paper_width, paper_height, paper_border, paper_angle);
} else {
paper_width = 200.0 * 72.0;
paper_height = 200.0 * 72.0;
hpgs_reader_set_dynamic_page(reader,&bbox,
paper_width, paper_height, paper_border, paper_angle);
}
image = (hpgs_image*)hpgs_new_png_image((int)bbox.urx, (int)bbox.ury, depth, palette, do_rop3);
image->vtable->write = &my_pim_write;
image = (hpgs_image *)realloc(image, sizeof(my_hpgs_png_image));
((my_hpgs_png_image *)image)->target = target;
pdv = hpgs_new_paint_device(image, NULL, &bbox, antialias);
hpgs_paint_device_set_image_interpolation(pdv, image_interpolation);
hpgs_paint_device_set_thin_alpha(pdv, thin_alpha);
plot_dev = (hpgs_device *)pdv;
if (hpgs_reader_imbue(reader, plot_dev)) {
fprintf(stderr, hpgs_i18n("Error: Cannot imbue plot device to reader: %s\n"),
hpgs_get_error());
err = B_NO_TRANSLATOR;
goto err2;
}
dataSize = (int)bbox.urx * 4 * (int)bbox.ury;
header.magic = B_TRANSLATOR_BITMAP;
header.bounds.Set(0, 0, (int)bbox.urx - 1, bbox.ury - 1);
header.rowBytes = (int)bbox.urx * 4;
header.colors = B_RGBA32;
header.dataSize = dataSize;
// write out Be's Bitmap header
swap_data(B_UINT32_TYPE, &header, sizeof(TranslatorBitmap),
B_SWAP_HOST_TO_BENDIAN);
bytesWritten = target->Write(&header, sizeof(TranslatorBitmap));
if (bytesWritten < B_OK) {
fprintf(stderr, "Write error %s\n", strerror(bytesWritten));
err = bytesWritten;
goto err2;
}
if ((size_t)bytesWritten != sizeof(TranslatorBitmap)) {
fprintf(stderr, "TranslatorBitmap\n");
err = B_IO_ERROR;
}
if (err == B_OK && hpgs_read(reader, HPGS_FALSE)) {
fprintf(stderr, hpgs_i18n("Error: Cannot process plot data %s\n"), hpgs_get_error());
err = B_NO_TRANSLATOR;
}
err2:
free(pdv);
free(image);
err1:
free(reader);
free(size_dev);
free(istream->stream);
free(istream);
return err;
}
BView *
HPGSTranslator::NewConfigView(TranslatorSettings *settings)
{
return new ConfigView(BRect(0, 0, 225, 175));
}
// #pragma mark -
BTranslator *
make_nth_translator(int32 n, image_id you, uint32 flags, ...)
{
if (n != 0)
return NULL;
return new HPGSTranslator();
}

View File

@ -0,0 +1,53 @@
/*
* Copyright 2007, Jérôme Duval. All rights reserved.
* Distributed under the terms of the MIT License.
*/
#ifndef HPGS_TRANSLATOR_H
#define HPGS_TRANSLATOR_H
#include "BaseTranslator.h"
#include <Translator.h>
#include <TranslatorFormats.h>
#include <TranslationDefs.h>
#include <GraphicsDefs.h>
#include <InterfaceDefs.h>
#include <DataIO.h>
#include <File.h>
#include <ByteOrder.h>
#define HPGS_TRANSLATOR_VERSION B_TRANSLATION_MAKE_VERSION(0, 1, 0)
#define HPGS_IMAGE_FORMAT 'HPGI'
#define HPGS_IN_QUALITY 0.90
#define HPGS_IN_CAPABILITY 0.90
#define BITS_IN_QUALITY 1
#define BITS_IN_CAPABILITY 1
#define HPGS_OUT_QUALITY 0.8
#define HPGS_OUT_CAPABILITY 0.8
#define BITS_OUT_QUALITY 1
#define BITS_OUT_CAPABILITY 0.9
class HPGSTranslator : public BaseTranslator {
public:
HPGSTranslator();
virtual ~HPGSTranslator();
virtual status_t DerivedIdentify(BPositionIO *inSource,
const translation_format *inFormat, BMessage *ioExtension,
translator_info *outInfo, uint32 outType);
virtual status_t DerivedTranslate(BPositionIO *inSource,
const translator_info *inInfo, BMessage *ioExtension,
uint32 outType, BPositionIO *outDestination, int32 baseType);
virtual BView *NewConfigView(TranslatorSettings *settings);
private:
};
#endif // HPGS_TRANSLATOR_H

View File

@ -0,0 +1,59 @@
SubDir HAIKU_TOP src add-ons translators hpgs ;
SubDirSysHdrs [ FDirName $(SUBDIR) lib ] ;
SubDirCcFlags -DHPGS_SHARED -std=c99 ;
UseLibraryHeaders zlib png ;
# Include code from shared translator directory
SEARCH_SOURCE += [ FDirName $(HAIKU_TOP) src add-ons translators shared ] ;
local sources =
hpgsbase.c
hpgsbbox.c
hpgsbezier.c
hpgs.c
hpgscharacter.c
hpgsdevices.c
hpgsfont.c
hpgsglobal.c
hpgsgstate.c
hpgsi18n.c
hpgsimage.c
hpgsimagerop.c
hpgsistream.c
hpgslabel.c
hpgslexer.c
hpgsmatrix.c
hpgsostream.c
hpgspaint.c
hpgspaintimage.c
hpgspaintpath.c
hpgspath.c
hpgspcl.c
hpgspe.c
hpgspen.c
hpgspjl.c
hpgsreader.c
hpgsrop.c
hpgsscanline.c
hpgssetup.c
hpgstransform.c
hpgszostream.c
;
Translator HPGSTranslator :
# HPGSTranslator classes
ConfigView.cpp
HPGSTranslator.cpp
$(sources)
# shared classes
BaseTranslator.cpp
TranslatorSettings.cpp
TranslatorWindow.cpp
: be translation libpng.so libtextencoding.so libz.so
: true
;
SEARCH on [ FGristFiles $(sources) ] = [ FDirName $(SUBDIR) lib ] ;

View File

@ -0,0 +1,127 @@
/*
* Copyright 2007, Jérôme Duval. All rights reserved.
* Distributed under the terms of the MIT License.
*/
#ifndef READ_HELPER_H
#define READ_HELPER_H
#include <errno.h>
#include <hpgs.h>
#include <DataIO.h>
typedef struct my_hpgs_istream_st
{
BPositionIO *stream;
status_t iseof;
} my_hpgs_istream;
static int
positionio_getc(my_hpgs_istream *stream)
{
unsigned char value;
status_t error;
stream->iseof = 0;
error = stream->stream->Read((void *)&value, sizeof(unsigned char));
if (error > B_OK)
return value;
stream->iseof = EOF;
return EOF;
}
static int
positionio_ungetc(int c, my_hpgs_istream *stream)
{
return stream->stream->Seek(-1, SEEK_CUR);
}
static int
positionio_close(my_hpgs_istream *stream)
{
return B_OK;
}
static int
positionio_eof(my_hpgs_istream *stream)
{
return stream->iseof;
}
static int
positionio_error(my_hpgs_istream *stream)
{
return errno;
}
static int
positionio_tell(my_hpgs_istream *stream, size_t *pos)
{
*pos = stream->stream->Position();
return 0;
}
static int
positionio_seek(my_hpgs_istream *stream, size_t pos)
{
stream->stream->Seek(pos, SEEK_SET);
return 0;
}
static int
positionio_seekend(my_hpgs_istream *stream, size_t pos)
{
stream->stream->Seek(pos, SEEK_END);
return 0;
}
static size_t
positionio_read(void *ptr, size_t size, size_t nmemb, my_hpgs_istream *stream)
{
unsigned char *iptr = (unsigned char *)ptr;
size_t i = 0;
for (; i < nmemb; i++) {
if (size != stream->stream->Read(iptr, size))
break;
iptr += size;
}
return i;
}
static hpgs_istream_vtable positionio_vtable =
{
(hpgs_istream_getc_func_t) positionio_getc,
(hpgs_istream_ungetc_func_t) positionio_ungetc,
(hpgs_istream_close_func_t) positionio_close,
(hpgs_istream_iseof_func_t) positionio_eof,
(hpgs_istream_iserror_func_t) positionio_error,
(hpgs_istream_seek_func_t) positionio_seek,
(hpgs_istream_tell_func_t) positionio_tell,
(hpgs_istream_read_func_t) positionio_read,
(hpgs_istream_seekend_func_t) positionio_seekend
};
hpgs_istream *hpgs_new_wrapper_istream(BPositionIO *stream)
{
hpgs_istream *ret = (hpgs_istream *)malloc(sizeof(hpgs_istream));
if (!ret)
return NULL;
ret->stream = (my_hpgs_istream *)malloc(sizeof(my_hpgs_istream));
ret->vtable = &positionio_vtable;
((my_hpgs_istream *)ret->stream)->iseof = 0;
((my_hpgs_istream *)ret->stream)->stream = stream;
return ret;
}
#endif // READ_HELPER_H

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,176 @@
/***********************************************************************
* *
* $Id: hpgsbase.c 270 2006-01-29 21:12:23Z softadm $
* *
* hpgs - HPGl Script, a hpgl/2 interpreter, which uses a Postscript *
* API for rendering a scene and thus renders to a variety of *
* devices and fileformats. *
* *
* (C) 2004-2006 ev-i Informationstechnologie GmbH http://www.ev-i.at *
* *
* Author: Wolfgang Glas *
* *
* hpgs is free software; you can redistribute it and/or *
* modify it under the terms of the GNU Lesser General Public *
* License as published by the Free Software Foundation; either *
* version 2.1 of the License, or (at your option) any later version. *
* *
* hpgs is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU *
* Lesser General Public License for more details. *
* *
* You should have received a copy of the GNU Lesser General Public *
* License along with this library; if not, write to the *
* Free Software Foundation, Inc., 59 Temple Place, Suite 330, *
* Boston, MA 02111-1307 USA *
* *
***********************************************************************
* *
* The implementation of basic helper functions. *
* *
***********************************************************************/
#include<hpgs.h>
#include<string.h>
/*!
Parses a physical paper size with a given unit and returns the
width and the height of the paper in PostScript pt (1/72 inch).
The standard formats A4,A3,A2,A1 an A0 as well
as their landscape counterparts A4l,A3l,A2l,A1l and A0l are
accepted.
If the string does not represent a standard paper size,
it must be of the format <width>x<height>, where <width>
and <height> must follow the convention of \c hpgs_parse_papersize.
The function returns 0, if the string matches these conventions or
-1, if the string is in a wrong format.
*/
int hpgs_parse_papersize(const char *str, double *pt_width, double *pt_height)
{
if (strcmp(str,"A4")==0)
{
*pt_width = 595.91084545538825881889;
*pt_height = 842.74519960822752756850;
}
else if (strcmp(str,"A3")==0)
{
*pt_width = 842.74519960822752756850;
*pt_height = 1191.82169091077651766614;
}
else if (strcmp(str,"A2")==0)
{
*pt_width = 1191.82169091077651766614;
*pt_height = 1685.49039921645505516535;
}
else if (strcmp(str,"A1")==0)
{
*pt_width = 1685.49039921645505516535;
*pt_height = 2383.64338182155303536062;
}
else if (strcmp(str,"A0")==0)
{
*pt_width = 2383.64338182155303536062;
*pt_height = 3370.98079843291011035905;
}
else if (strcmp(str,"A4l")==0)
{
*pt_height = 595.91084545538825881889;
*pt_width = 842.74519960822752756850;
}
else if (strcmp(str,"A3l")==0)
{
*pt_height = 842.74519960822752756850;
*pt_width = 1191.82169091077651766614;
}
else if (strcmp(str,"A2l")==0)
{
*pt_height = 1191.82169091077651766614;
*pt_width = 1685.49039921645505516535;
}
else if (strcmp(str,"A1l")==0)
{
*pt_height = 1685.49039921645505516535;
*pt_width = 2383.64338182155303536062;
}
else if (strcmp(str,"A0l")==0)
{
*pt_height = 2383.64338182155303536062;
*pt_width = 3370.98079843291011035905;
}
else
{
// find the 'x'
const char *x=strchr(str,'x');
char wstr[32];
int l;
if (!x) return -1;
l=x-str;
if (l > 31) return -1;
strncpy(wstr,str,l);
wstr[l] = '\0';
if (hpgs_parse_length(wstr,pt_width)) return -1;
if (hpgs_parse_length(str+l+1,pt_height)) return -1;
}
return 0;
}
/*!
Parses a physical length with a given unit and returns the length
in PostScript pt (1/72 inch).
The following formats are accepted:
\verbatim
27
37pt
4.5inch
0.37m
1.5cm
11.34mm
\endverbatim
If no unit is specified, PostScript points (1/72 inch) are assumed.
The function returns 0, if the string matches these conventions or
-1, if the string is in a wrong format.
*/
int hpgs_parse_length(const char *str, double *pt_length)
{
const char *unit="pt";
char * endptr = (char*)str;
*pt_length = strtod(str,&endptr);
if (endptr == str) return -1;
if (*endptr) unit = endptr;
if (strcmp(unit,"cm")==0)
{
*pt_length *= 72.0 / 2.54;
}
else if (strcmp(unit,"mm")==0)
{
*pt_length *= 72.0 / 25.4;
}
else if (strcmp(unit,"m")==0)
{
*pt_length *= 72.0 / 0.0254;
}
else if (strcmp(unit,"inch")==0)
{
*pt_length *= 72.0;
}
else if (strcmp(unit,"pt"))
return -1;
return 0;
}

View File

@ -0,0 +1,142 @@
/***********************************************************************
* *
* $Id: hpgsbbox.c 298 2006-03-05 18:18:03Z softadm $
* *
* hpgs - HPGl Script, a hpgl/2 interpreter, which uses a Postscript *
* API for rendering a scene and thus renders to a variety of *
* devices and fileformats. *
* *
* (C) 2004-2006 ev-i Informationstechnologie GmbH http://www.ev-i.at *
* *
* Author: Wolfgang Glas *
* *
* hpgs is free software; you can redistribute it and/or *
* modify it under the terms of the GNU Lesser General Public *
* License as published by the Free Software Foundation; either *
* version 2.1 of the License, or (at your option) any later version. *
* *
* hpgs is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU *
* Lesser General Public License for more details. *
* *
* You should have received a copy of the GNU Lesser General Public *
* License along with this library; if not, write to the *
* Free Software Foundation, Inc., 59 Temple Place, Suite 330, *
* Boston, MA 02111-1307 USA *
* *
***********************************************************************
* *
* The implementation of the public API for bounding boxes. *
* *
***********************************************************************/
#include<hpgs.h>
/*!
Returns, whether the two bounding boxes are equal.
*/
hpgs_bool hpgs_bbox_isequal (const hpgs_bbox *bb1, const hpgs_bbox *bb2)
{
return
bb1->llx == bb2->llx &&
bb1->lly == bb2->lly &&
bb1->urx == bb2->urx &&
bb1->ury == bb2->ury;
}
/*!
Calculates the distance of the two bounding boxes.
*/
void hpgs_bbox_distance (hpgs_point *d, const hpgs_bbox *bb1, const hpgs_bbox *bb2)
{
if (hpgs_bbox_isnull(bb1) ||
hpgs_bbox_isnull(bb2) )
{
d->x = 0.0;
d->y = 0.0;
return;
}
if (bb2->llx >= bb1->urx)
{
d->x = bb2->llx - bb1->urx;
}
else if (bb1->llx >= bb2->urx)
{
d->x = bb1->llx - bb2->urx;
}
else
d->x = 0.0;
if (bb2->lly >= bb1->ury)
{
d->y = bb2->lly - bb1->ury;
}
else if (bb1->lly >= bb2->ury)
{
d->y = bb1->lly - bb2->ury;
}
else
d->y = 0.0;
}
/*!
Returns, whether the bounding box is null.
A null bounding box is als empty.
An empty bounding box may not be null, if
either of the x or y extend of the bounding box
is exactly zero.
*/
hpgs_bool hpgs_bbox_isnull (const hpgs_bbox *bb)
{
return
bb->llx > bb->urx ||
bb->lly > bb->ury;
}
/*!
Returns, whether the bounding box is empty.
*/
hpgs_bool hpgs_bbox_isempty (const hpgs_bbox *bb)
{
return
bb->llx >= bb->urx ||
bb->lly >= bb->ury;
}
/*!
Sets this bounding box to an empty bounding box.
*/
void hpgs_bbox_null (hpgs_bbox *bb)
{
bb->llx = 1.0e20;
bb->lly = 1.0e20;
bb->urx = -1.0e20;
bb->ury = -1.0e20;
}
/*!
Expands \c bb1 in order to comprise the smallest bounding box
containing both \c bb1 and \c bb2
*/
void hpgs_bbox_expand (hpgs_bbox *bb1, const hpgs_bbox *bb2)
{
if (bb2->llx < bb1->llx) bb1->llx = bb2->llx;
if (bb2->lly < bb1->lly) bb1->lly = bb2->lly;
if (bb2->urx > bb1->urx) bb1->urx = bb2->urx;
if (bb2->ury > bb1->ury) bb1->ury = bb2->ury;
}
/*!
Shrinks \c bb1 in order to comprise the intersection
of \c bb1 and \c bb2. If the bounding boxes do not intersect,
\c bb1 is set to a null bounding box.
*/
void hpgs_bbox_intersect (hpgs_bbox *bb1, const hpgs_bbox *bb2)
{
if (bb2->llx > bb1->llx) bb1->llx=bb2->llx;
if (bb2->lly > bb1->lly) bb1->lly=bb2->lly;
if (bb2->urx < bb1->urx) bb1->urx=bb2->urx;
if (bb2->ury < bb1->ury) bb1->ury=bb2->ury;
}

View File

@ -0,0 +1,580 @@
/***********************************************************************
* *
* $Id: hpgsbezier.c 270 2006-01-29 21:12:23Z softadm $
* *
* hpgs - HPGl Script, a hpgl/2 interpreter, which uses a Postscript *
* API for rendering a scene and thus renders to a variety of *
* devices and fileformats. *
* *
* (C) 2004-2006 ev-i Informationstechnologie GmbH http://www.ev-i.at *
* *
* Author: Wolfgang Glas *
* *
* hpgs is free software; you can redistribute it and/or *
* modify it under the terms of the GNU Lesser General Public *
* License as published by the Free Software Foundation; either *
* version 2.1 of the License, or (at your option) any later version. *
* *
* hpgs is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU *
* Lesser General Public License for more details. *
* *
* You should have received a copy of the GNU Lesser General Public *
* License along with this library; if not, write to the *
* Free Software Foundation, Inc., 59 Temple Place, Suite 330, *
* Boston, MA 02111-1307 USA *
* *
***********************************************************************
* *
* Bezier spline length and scanline cut implementation. *
* *
***********************************************************************/
#include <hpgspaint.h>
#include <math.h>
#include <assert.h>
// #define HPGS_BEZIER_DEBUG
/*! Calculates the derivation of the bezier curve starting
at point \c i of \c path at curve parameter \c t.
*/
void hpgs_bezier_path_delta(const hpgs_paint_path *path, int i,
double t, hpgs_point *p)
{
double tp,tm;
tp = t + 0.5;
tm = 0.5 - t;
p->x = 3.0* ((path->points[i+1].p.x-path->points[i].p.x)*tm*tm+
2.0 * (path->points[i+2].p.x-path->points[i+1].p.x) * tm*tp+
(path->points[i+3].p.x-path->points[i+2].p.x) * tp*tp);
p->y = 3.0 * ((path->points[i+1].p.y-path->points[i].p.y)*tm*tm+
2.0 * (path->points[i+2].p.y-path->points[i+1].p.y) * tm*tp+
(path->points[i+3].p.y-path->points[i+2].p.y) * tp*tp);
}
/*! Calculates the derivation of the bezier curve starting
at point \c i of \c path at curve parameter \c t.
*/
double hpgs_bezier_path_delta_x(const hpgs_paint_path *path, int i, double t)
{
double tp,tm;
tp = t + 0.5;
tm = 0.5 - t;
return 3.0* ((path->points[i+1].p.x-path->points[i].p.x)*tm*tm+
2.0 * (path->points[i+2].p.x-path->points[i+1].p.x) * tm*tp+
(path->points[i+3].p.x-path->points[i+2].p.x) * tp*tp);
}
/*! Calculates the derivation of the bezier curve starting
at point \c i of \c path at curve parameter \c t.
*/
double hpgs_bezier_path_delta_y(const hpgs_paint_path *path, int i, double t)
{
double tp,tm;
tp = t + 0.5;
tm = 0.5 - t;
return 3.0* ((path->points[i+1].p.y-path->points[i].p.y)*tm*tm+
2.0 * (path->points[i+2].p.y-path->points[i+1].p.y) * tm*tp+
(path->points[i+3].p.y-path->points[i+2].p.y) * tp*tp);
}
/*! Calculates the tangent to the bezier curve starting
at point \c i of \c path at curve parameter \c t.
If \c orientation is \c 1, the tangent is calculated with increasing
curve parameter, if we meet a singularity (right tangent).
If \c orientation is \c -1, the tangent is calculated with decreasing
curve parameter, if we meet a singularity (left tangent).
If \c orientation is \c 0, the tangent is calculated with decreased
and increased curve parameter, if we meet a singularity (mid tangent).
*/
void hpgs_bezier_path_tangent(const hpgs_paint_path *path, int i,
double t, int orientation,
double ytol, hpgs_point *p)
{
hpgs_bezier_path_delta(path,i,t,p);
double l = hypot(p->x,p->y);
if (l < ytol)
{
hpgs_point p1;
if (orientation <= 0)
hpgs_bezier_path_point(path,i,t-1.0e-4,&p1);
else
hpgs_bezier_path_point(path,i,t,&p1);
if (orientation >= 0)
hpgs_bezier_path_point(path,i,t+1.0e-4,p);
else
hpgs_bezier_path_point(path,i,t,p);
p->x -= p1.x;
p->y -= p1.y;
l = hypot(p->x,p->y);
if (l < ytol*1.0e-4) return;
}
p->x /= l;
p->y /= l;
}
static int quad_roots (double a, double b, double c,
double t0, double t1, double *t)
{
if (fabs(a) < (fabs(b)>fabs(c) ? fabs(b) : fabs(c)) * 1.0e-8 || fabs(a) < 1.0e-16)
{
if (fabs(b) < fabs(c) * 1.0e-8)
return 0;
t[0] = -c/b;
return t[0] > t0 && t[0] < t1;
}
double p = b/a;
double q = c/a;
double det = 0.25*p-q;
if (det < 0) return 0;
det = sqrt(det);
if (p > 0.0)
t[0] = -0.5*p - det;
else
t[0] = -0.5*p + det;
if (fabs(t[0]) < 1.0e-8)
return t[0] > t0 && t[0] < t1;
t[1] = q / t[0];
if (t[0] <= t0 || t[0] >= t1)
{
t[0] = t[1];
return t[0] > t0 && t[0] < t1;
}
if (t[1] <= t0 || t[1] >= t1)
return 1;
if (t[0] > t[1])
{
double tmp = t[1];
t[1] = t[0];
t[0] = tmp;
}
return fabs(t[0]-t[1]) < 1.0e-8 ? 1 : 2;
}
/*!
Calculates the singularities of the bezier curve in the
parameter interval from \c t0 to \c t1.
We calculate points, where the cross product of the first derivative
and the second derivative vanishes. These points include points, where
the first or second derivative vanishes. Additionally, turning points
of the curve are also included.
\c tx is a pointer to an array of at least two double values,
in which the position of the singularities is returned.
*/
void hpgs_bezier_path_singularities(const hpgs_paint_path *path, int i,
double t0, double t1,
int *nx, double *tx)
{
// The second order spline p'(t) cross p''(t)
double k0 =
(path->points[i+1].p.x-path->points[i].p.x)*(path->points[i+2].p.y-path->points[i+1].p.y) -
(path->points[i+1].p.y-path->points[i].p.y)*(path->points[i+2].p.x-path->points[i+1].p.x);
double k1 =
(path->points[i+1].p.x-path->points[i].p.x)*(path->points[i+3].p.y-path->points[i+2].p.y) -
(path->points[i+1].p.y-path->points[i].p.y)*(path->points[i+3].p.x-path->points[i+2].p.x);
double k2 =
(path->points[i+2].p.x-path->points[i+1].p.x)*(path->points[i+3].p.y-path->points[i+2].p.y) -
(path->points[i+2].p.y-path->points[i+1].p.y)*(path->points[i+3].p.x-path->points[i+2].p.x);
// coefficients for the quadratic equations.
double a = k0 - k1 + k2;
double b = k2 - k0;
double c = 0.25 * (k0 + k1 + k2);
*nx = quad_roots (a,b,c,t0,t1,tx);
}
static void add_quad (const hpgs_point *p1,
const hpgs_point *d1,
const hpgs_point *p2,
const hpgs_point *d2,
int *nx, hpgs_point *points)
{
double det = d1->y * d2->x - d1->x * d2->y;
if (fabs(det) < 1.0e-8)
{
points[*nx].x = 0.5 * (p1->x + p2->x);
points[*nx].y = 0.5 * (p1->y + p2->y);
++*nx;
}
else
{
double s = (d2->x*(p2->y-p1->y)-
d2->y*(p2->x-p1->x) )/det;
points[*nx].x = p1->x + s*d1->x;
points[*nx].y = p1->y + s*d1->y;
++*nx;
}
points[*nx].x = p2->x;
points[*nx].y = p2->y;
++*nx;
}
/*!
Approximates the bezier curve segment in the
parameter interval from \c t0 to \c t1 with quadratic bezier splines.
The array \c points is used to return the quadratic bezier segments and
must have a dimension of at least 16 points.
\c nx returns the number of generated points, which is always an even
number. The first point is the control point of the first quadratic
spline, the second point the endpoint of the first quadratic spline
and so on.
*/
void hpgs_bezier_path_to_quadratic(const hpgs_paint_path *path, int i,
double t0, double t1,
int *nx, hpgs_point *points)
{
// The second order spline p'(t) cross p''(t)
double k0 =
(path->points[i+1].p.x-path->points[i].p.x)*(path->points[i+2].p.y-path->points[i+1].p.y) -
(path->points[i+1].p.y-path->points[i].p.y)*(path->points[i+2].p.x-path->points[i+1].p.x);
double k1 =
(path->points[i+1].p.x-path->points[i].p.x)*(path->points[i+3].p.y-path->points[i+2].p.y) -
(path->points[i+1].p.y-path->points[i].p.y)*(path->points[i+3].p.x-path->points[i+2].p.x);
double k2 =
(path->points[i+2].p.x-path->points[i+1].p.x)*(path->points[i+3].p.y-path->points[i+2].p.y) -
(path->points[i+2].p.y-path->points[i+1].p.y)*(path->points[i+3].p.x-path->points[i+2].p.x);
double xmax,xmin,ymin,ymax;
// coefficients for the quadratic equations.
double a = k0 - k1 + k2;
double b = k2 - k0;
double c = 0.25 * (k0 + k1 + k2);
// at most three partition points:
// extrem, roots of the curvature spline
double tpart[5];
// get the roots.
int ipart;
int npart = quad_roots (a,b,c,t0,t1,tpart+1) + 1;
// add the extreme point.
if (fabs(a) > fabs(b))
{
double text = -0.5 * b/a;
if (npart == 3)
{
tpart[3] = tpart[2];
tpart[2] = text;
npart = 3;
}
else if (text > t0 && text < t1)
{
if (npart == 2 && text < tpart[1])
{
tpart[2] = tpart[1];
tpart[1] = text;
}
else
tpart[npart] = text;
++npart;
}
}
tpart[0] = t0;
tpart[npart] = t1;
xmax = xmin = path->points[i].p.x;
if (path->points[i+1].p.x > xmax) xmax = path->points[i+1].p.x;
if (path->points[i+2].p.x > xmax) xmax = path->points[i+2].p.x;
if (path->points[i+3].p.x > xmax) xmax = path->points[i+3].p.x;
if (path->points[i+1].p.x < xmin) xmin = path->points[i+1].p.x;
if (path->points[i+2].p.x < xmin) xmin = path->points[i+2].p.x;
if (path->points[i+3].p.x < xmin) xmin = path->points[i+3].p.x;
ymax = ymin = path->points[i].p.y;
if (path->points[i+1].p.y > ymax) ymax = path->points[i+1].p.y;
if (path->points[i+2].p.y > ymax) ymax = path->points[i+2].p.y;
if (path->points[i+3].p.y > ymax) ymax = path->points[i+3].p.y;
if (path->points[i+1].p.y < ymin) ymin = path->points[i+1].p.y;
if (path->points[i+2].p.y < ymin) ymin = path->points[i+2].p.y;
if (path->points[i+3].p.y < ymin) ymin = path->points[i+3].p.y;
double curv0 =
k0*(0.5-tpart[0])*(0.5-tpart[0]) +
k1*(0.5-tpart[0])*(0.5+tpart[0]) +
k2*(0.5+tpart[0])*(0.5+tpart[0]);
*nx = 0;
for (ipart=0; ipart<npart; ++ipart)
{
double curv1 =
k0*(0.5-tpart[ipart+1])*(0.5-tpart[ipart+1]) +
k1*(0.5-tpart[ipart+1])*(0.5+tpart[ipart+1]) +
k2*(0.5+tpart[ipart+1])*(0.5+tpart[ipart+1]);
int n_splines = 1;
if (fabs(xmax-xmin)<1.0e-8 && fabs(ymax-ymin) < 1.0e-8)
n_splines = (int)(16.0 * fabs(curv0-curv1)/((xmax-xmin)*(ymax-ymin)));
int j;
if (n_splines < 1) n_splines = 1;
else if (n_splines > 8/npart) n_splines = 8/npart;
hpgs_point d1;
hpgs_point p1;
hpgs_bezier_path_point(path,i,tpart[ipart],&p1);
hpgs_bezier_path_tangent(path,i,tpart[ipart],1,1.0e-3,&d1);
for (j=1;j<=n_splines;++j)
{
double t = tpart[ipart] + (tpart[ipart+1]-tpart[ipart]) * j / (double)n_splines;
hpgs_point d2;
hpgs_point p2;
hpgs_bezier_path_point(path,i,t,&p2);
hpgs_bezier_path_tangent(path,i,t,j<n_splines ? 0 : -1,1.0e-3,&d2);
add_quad(&p1,&d1,&p2,&d2,nx,points);
p1 = p2;
d1 = d2;
}
curv0 = curv1;
}
}
/* Internal: Calculates the derivation of the curve length
of the bezier curve \c b at curve parameter \c t.
*/
static double bezier_dl(const hpgs_paint_path *path, int i, double t)
{
double tp,tm;
tp = t + 0.5;
tm = 0.5 - t;
return 3.0*hypot((path->points[i+1].p.x-path->points[i].p.x)*tm*tm+
2.0 * (path->points[i+2].p.x-path->points[i+1].p.x) * tm*tp+
(path->points[i+3].p.x-path->points[i+2].p.x) * tp*tp,
(path->points[i+1].p.y-path->points[i].p.y)*tm*tm+
2.0 * (path->points[i+2].p.y-path->points[i+1].p.y) * tm*tp+
(path->points[i+3].p.y-path->points[i+2].p.y) * tp*tp
);
}
/*! Calculates the curve lengths at an equidistant grid
of curve parmeters by na numerical quadrature.
You must call this subroutine before using
\c hpgs_bezier_length_param.
*/
void hpgs_bezier_length_init(hpgs_bezier_length *b,
const hpgs_paint_path *path, int i)
{
int ip;
b->dl[0] = bezier_dl(path,i,-0.5);
b->l[0] = 0.0;
for (ip=1;ip<=16;++ip)
{
double dlm0,dlm1;
// Lobatto quadrature with order 4.
b->dl[ip] = bezier_dl(path,i,(ip-8.0)*0.0625);
dlm0 = bezier_dl(path,i,(ip-(8.5+0.22360679774997896964))*0.0625);
dlm1 = bezier_dl(path,i,(ip-(8.5-0.22360679774997896964))*0.0625);
b->l[ip] = b->l[ip-1] +
(b->dl[ip-1] + 5.0 * (dlm0 + dlm1) + b->dl[ip])/(16.0*12.0);
}
}
/*! Returns the curve parameter at the bezier curve \c b
corresponding to a curve length \c l.
You must have called \c hpgs_bezier_length_init before using
this function.
*/
double hpgs_bezier_length_param(const hpgs_bezier_length *b, double l)
{
// binary search.
int i = 0;
if (l >= b->l[i+8]) i+=8;
if (l >= b->l[i+4]) i+=4;
if (l >= b->l[i+2]) i+=2;
if (l >= b->l[i+1]) ++i;
double dl = b->l[i+1]-b->l[i];
double ll = (l-b->l[i])/dl;
return
(i - 8.0 + ll*ll*(3.0-2.0*ll)) * 0.0625 +
(ll*(ll*(ll-2.0)+1.0) / b->dl[i] + ll*ll*(ll-1.0) / b->dl[i+1] ) * dl;
}
/*! Calculates the minimal x component of all four control points of
the bezier spline. */
double hpgs_bezier_path_xmin (const hpgs_paint_path *path, int i)
{
double x0 =
path->points[i].p.x < path->points[i+1].p.x ?
path->points[i].p.x : path->points[i+1].p.x;
double x1 =
path->points[i+2].p.x < path->points[i+3].p.x ?
path->points[i+2].p.x : path->points[i+3].p.x;
return x0 < x1 ? x0 : x1;
}
/*! Calculates the maximal x component of all four control points of
the bezier spline. */
double hpgs_bezier_path_xmax (const hpgs_paint_path *path, int i)
{
double x0 =
path->points[i].p.x > path->points[i+1].p.x ?
path->points[i].p.x : path->points[i+1].p.x;
double x1 =
path->points[i+2].p.x > path->points[i+3].p.x ?
path->points[i+2].p.x : path->points[i+3].p.x;
return x0 > x1 ? x0 : x1;
}
/*! Calculates the minimal y component of all four control points of
the bezier spline. */
double hpgs_bezier_path_ymin (const hpgs_paint_path *path, int i)
{
double y0 =
path->points[i].p.y < path->points[i+1].p.y ?
path->points[i].p.y : path->points[i+1].p.y;
double y1 =
path->points[i+2].p.y < path->points[i+3].p.y ?
path->points[i+2].p.y : path->points[i+3].p.y;
return y0 < y1 ? y0 : y1;
}
/*! Calculates the maximal y component of all four control points of
the bezier spline. */
double hpgs_bezier_path_ymax (const hpgs_paint_path *path, int i)
{
double y0 =
path->points[i].p.y > path->points[i+1].p.y ?
path->points[i].p.y : path->points[i+1].p.y;
double y1 =
path->points[i+2].p.y > path->points[i+3].p.y ?
path->points[i+2].p.y : path->points[i+3].p.y;
return y0 > y1 ? y0 : y1;
}
/*! Calculates the x component of a point on the bezier spline. */
double hpgs_bezier_path_x (const hpgs_paint_path *path, int i, double t)
{
double tp,tm;
tp = t + 0.5;
tm = 0.5 - t;
return
path->points[i].p.x *tm*tm*tm +
3.0 * tm*tp * (path->points[i+1].p.x * tm + path->points[i+2].p.x * tp) +
path->points[i+3].p.x * tp*tp*tp;
}
/*! Calculates the y component of a point on the bezier spline. */
double hpgs_bezier_path_y (const hpgs_paint_path *path, int i, double t)
{
double tp,tm;
tp = t + 0.5;
tm = 0.5 - t;
return
path->points[i].p.y *tm*tm*tm +
3.0 * tm*tp * (path->points[i+1].p.y * tm + path->points[i+2].p.y * tp) +
path->points[i+3].p.y * tp*tp*tp;
}
/*! Calculates the point on the bezier curve starting
at point \c i of \c path at curve parameter \c t.
*/
void hpgs_bezier_path_point(const hpgs_paint_path *path, int i,
double t, hpgs_point *p)
{
double tp,tm;
tp = t + 0.5;
tm = 0.5 - t;
p->x =
path->points[i].p.x *tm*tm*tm +
3.0 * tm*tp * (path->points[i+1].p.x * tm + path->points[i+2].p.x * tp) +
path->points[i+3].p.x * tp*tp*tp;
p->y =
path->points[i].p.y *tm*tm*tm +
3.0 * tm*tp * (path->points[i+1].p.y * tm + path->points[i+2].p.y * tp) +
path->points[i+3].p.y * tp*tp*tp;
}

View File

@ -0,0 +1,686 @@
/***********************************************************************
* *
* $Id: hpgscharacter.c 383 2007-03-18 18:29:22Z softadm $
* *
* hpgs - HPGl Script, a hpgl/2 interpreter, which uses a Postscript *
* API for rendering a scene and thus renders to a variety of *
* devices and fileformats. *
* *
* (C) 2004-2006 ev-i Informationstechnologie GmbH http://www.ev-i.at *
* *
* Author: Wolfgang Glas *
* *
* hpgs is free software; you can redistribute it and/or *
* modify it under the terms of the GNU Lesser General Public *
* License as published by the Free Software Foundation; either *
* version 2.1 of the License, or (at your option) any later version. *
* *
* hpgs is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU *
* Lesser General Public License for more details. *
* *
* You should have received a copy of the GNU Lesser General Public *
* License along with this library; if not, write to the *
* Free Software Foundation, Inc., 59 Temple Place, Suite 330, *
* Boston, MA 02111-1307 USA *
* *
***********************************************************************
* *
* The implementation of the HPGL reader. *
* *
***********************************************************************/
#include <hpgsreader.h>
#include <math.h>
#include <string.h>
#include <ctype.h>
// The size of a line feed measured in the cap height of a font.
#define HPGS_LF_FAC 1.75
#define HPGS_VSPACE_FAC 1.5
/*
HPGL command AD (Alternate font Definition)
*/
int hpgs_reader_do_AD (hpgs_reader *reader)
{
while (!reader->eoc)
{
int kind;
if (hpgs_reader_read_int(reader,&kind)) return -1;
if (reader->eoc) return -1;
switch (kind)
{
case 1:
if (hpgs_reader_read_int(reader,&reader->alternate_encoding))
return -1;
break;
case 2:
if (hpgs_reader_read_int(reader,&reader->alternate_spacing))
return -1;
break;
case 3:
if (hpgs_reader_read_double(reader,&reader->alternate_pitch))
return -1;
break;
case 4:
if (hpgs_reader_read_double(reader,&reader->alternate_height))
return -1;
break;
case 5:
if (hpgs_reader_read_int(reader,&reader->alternate_posture))
return -1;
break;
case 6:
if (hpgs_reader_read_int(reader,&reader->alternate_weight))
return -1;
break;
case 7:
if (hpgs_reader_read_int(reader,&reader->alternate_face))
return -1;
break;
default:
return -1;
}
}
return 0;
}
/*
HPGL command SD (Standard font Definition)
*/
int hpgs_reader_do_SD (hpgs_reader *reader)
{
while (!reader->eoc)
{
int kind;
if (hpgs_reader_read_int(reader,&kind)) return -1;
if (reader->eoc) return -1;
switch (kind)
{
case 1:
if (hpgs_reader_read_int(reader,&reader->default_encoding))
return -1;
break;
case 2:
if (hpgs_reader_read_int(reader,&reader->default_spacing))
return -1;
break;
case 3:
if (hpgs_reader_read_double(reader,&reader->default_pitch))
return -1;
break;
case 4:
if (hpgs_reader_read_double(reader,&reader->default_height))
return -1;
break;
case 5:
if (hpgs_reader_read_int(reader,&reader->default_posture))
return -1;
break;
case 6:
if (hpgs_reader_read_int(reader,&reader->default_weight))
return -1;
break;
case 7:
if (hpgs_reader_read_int(reader,&reader->default_face))
return -1;
break;
default:
return -1;
}
}
return 0;
}
/*
HPGL command CP (Character Plot)
*/
int hpgs_reader_do_CP (hpgs_reader *reader)
{
double w,h,ca,sa,spaces=0.0;
double lines=reader->current_text_line ? 1.0 : -1.0;
hpgs_point space_vec;
hpgs_point lf_vec;
if (hpgs_reader_checkpath(reader)) return -1;
if (reader->eoc)
reader->current_point = reader->cr_point;
else
{
if (hpgs_reader_read_double(reader,&spaces)) return -1;
if (hpgs_reader_read_double(reader,&lines)) return -1;
}
w =
reader->current_char_size.x ? (1.5 * reader->current_char_size.x) :
(72.0 / (reader->alternate_font ?
reader->alternate_pitch :
reader->default_pitch ));
h =
reader->current_char_size.y ? reader->current_char_size.y :
(reader->alternate_font ?
reader->alternate_height :
reader->default_height );
ca = cos(reader->current_label_angle);
sa = sin(reader->current_label_angle);
switch (reader->current_text_path % 4)
{
case 0:
space_vec.x = ca * (1.0+reader->current_extra_space.x) * w;
space_vec.y = sa * (1.0+reader->current_extra_space.x) * w;
lf_vec.x = sa * (HPGS_LF_FAC+reader->current_extra_space.y) * h;
lf_vec.y = -ca * (HPGS_LF_FAC+reader->current_extra_space.y) * h;
break;
case 1:
space_vec.x = sa * (HPGS_VSPACE_FAC+reader->current_extra_space.y) * h;
space_vec.y = -ca * (HPGS_VSPACE_FAC+reader->current_extra_space.y) * h;
lf_vec.x = -ca * (HPGS_LF_FAC+reader->current_extra_space.x) * w;
lf_vec.y = -sa * (HPGS_LF_FAC+reader->current_extra_space.x) * w;
break;
case 2:
space_vec.x = -ca * (1.0+reader->current_extra_space.x) * w;
space_vec.y = -sa * (1.0+reader->current_extra_space.x) * w;
lf_vec.x = -sa * (HPGS_LF_FAC+reader->current_extra_space.y) * h;
lf_vec.y = ca * (HPGS_LF_FAC+reader->current_extra_space.y) * h;
break;
default: // 3
space_vec.x = -sa * (HPGS_VSPACE_FAC+reader->current_extra_space.y) * h;
space_vec.y = ca * (HPGS_VSPACE_FAC+reader->current_extra_space.y) * h;
lf_vec.x = ca * (HPGS_LF_FAC+reader->current_extra_space.x) * w;
lf_vec.y = sa * (HPGS_LF_FAC+reader->current_extra_space.x) * w;
}
if (reader->current_text_line)
lines = -lines;
reader->current_point.x += space_vec.x * spaces;
reader->current_point.y += space_vec.y * spaces;
reader->current_point.x += lf_vec.x * lines;
reader->current_point.y += lf_vec.y * lines;
return 0;
}
/*
HPGL command DI (absolute DIrection)
*/
int hpgs_reader_do_DI (hpgs_reader *reader)
{
double run = 1.0;
double rise = 0.0;
if (!reader->eoc)
{
if (hpgs_reader_read_double(reader,&run)) return -1;
if (hpgs_reader_read_double(reader,&rise)) return -1;
}
reader->current_label_angle = atan2(rise,run);
return 0;
}
/*
HPGL command DR (Relative Direction)
*/
int hpgs_reader_do_DR (hpgs_reader *reader)
{
double run = 0.01;
double rise = 0.0;
if (!reader->eoc)
{
if (hpgs_reader_read_double(reader,&run)) return -1;
if (hpgs_reader_read_double(reader,&rise)) return -1;
}
run *= (reader->P2.x - reader->P1.x);
rise *= (reader->P2.y - reader->P1.y);
reader->current_label_angle = atan2(rise,run);
return 0;
}
/*
HPGL command DV (Define Variable Text path)
*/
int hpgs_reader_do_DV (hpgs_reader *reader)
{
reader->current_text_path = 0;
reader->current_text_line = 0;
if (!reader->eoc &&
hpgs_reader_read_int(reader,&reader->current_text_path)) return -1;
if (!reader->eoc &&
hpgs_reader_read_int(reader,&reader->current_text_line)) return -1;
return 0;
}
/*
HPGL command ES (Extra Space)
*/
int hpgs_reader_do_ES (hpgs_reader *reader)
{
reader->current_extra_space.x = 0.0;
reader->current_extra_space.y = 0.0;
if (!reader->eoc &&
hpgs_reader_read_double(reader,&reader->current_extra_space.x)) return -1;
if (!reader->eoc &&
hpgs_reader_read_double(reader,&reader->current_extra_space.y)) return -1;
return 0;
}
/*
HPGL command LO (Label Origin)
*/
int hpgs_reader_do_LO (hpgs_reader *reader)
{
reader->current_label_origin = 1;
if (!reader->eoc &&
hpgs_reader_read_int(reader,&reader->current_label_origin)) return -1;
return 0;
}
/*
HPGL command SI (absolute character SIze)
*/
int hpgs_reader_do_SI (hpgs_reader *reader)
{
reader->current_char_size.x = 0.0;
reader->current_char_size.y = 0.0;
if (reader->eoc) return 0;
if (hpgs_reader_read_double(reader,&reader->current_char_size.x)) return -1;
if (hpgs_reader_read_double(reader,&reader->current_char_size.y)) return -1;
reader->current_char_size.x *= 72.0 / 2.54;
reader->current_char_size.y *= 72.0 / 2.54;
return 0;
}
/*
HPGL command SR (Relative character Size)
*/
int hpgs_reader_do_SR (hpgs_reader *reader)
{
reader->current_char_size.x = 0.0;
reader->current_char_size.y = 0.0;
if (reader->eoc) return 0;
if (hpgs_reader_read_double(reader,&reader->current_char_size.x)) return -1;
if (hpgs_reader_read_double(reader,&reader->current_char_size.y)) return -1;
reader->current_char_size.x *= (reader->P2.x-reader->P1.x) * 0.01 * HP_TO_PT;
reader->current_char_size.y *= (reader->P2.y-reader->P1.y) * 0.01 * HP_TO_PT;
return 0;
}
/*
HPGL command SL (character SLant)
*/
int hpgs_reader_do_SL (hpgs_reader *reader)
{
reader->current_slant = 0.0;
if (!reader->eoc &&
hpgs_reader_read_double(reader,&reader->current_slant)) return -1;
return 0;
}
/*
HPGL command SA (Select Alternate font)
*/
int hpgs_reader_do_SA (hpgs_reader *reader)
{
reader->alternate_font = 1;
return 0;
}
/*
HPGL command SS (Select Standard font)
*/
int hpgs_reader_do_SS(hpgs_reader *reader)
{
reader->alternate_font = 0;
return 0;
}
/*
HPGL command DT (Define label Terminator)
*/
int hpgs_reader_do_DT (hpgs_reader *reader)
{
reader->bytes_ignored = 0;
reader->last_byte = hpgs_getc(reader->in);
if (reader->last_byte == EOF)
return -1;
if (reader->last_byte == ';')
{
reader->label_term = '\003';
reader->label_term_ignore = 1;
reader->eoc = 1;
return 0;
}
else
{
reader->label_term = reader->last_byte;
reader->last_byte = hpgs_getc(reader->in);
if (reader->last_byte == EOF)
return -1;
}
if (reader->last_byte == ',')
{
reader->label_term_ignore = 0;
while (isspace(reader->last_byte = hpgs_getc(reader->in))) ;
while (isdigit(reader->last_byte = hpgs_getc(reader->in)))
if (reader->last_byte != '0')
reader->label_term_ignore = 1;
if (reader->last_byte == EOF)
return -1;
}
else
reader->label_term_ignore = 1;
while (isspace(reader->last_byte)) reader->last_byte = hpgs_getc(reader->in);
if (isalpha(reader->last_byte) || reader->last_byte == HPGS_ESC)
reader->bytes_ignored = 1;
else
{
if (reader->last_byte != ';')
return -1;
reader->bytes_ignored = 0;
}
reader->eoc = 1;
return 0;
}
/*
HPGL command SM (Symbol Mode)
*/
int hpgs_reader_do_SM (hpgs_reader *reader)
{
reader->bytes_ignored = 0;
if (reader->eoc)
return 0;
reader->last_byte = hpgs_getc(reader->in);
if (reader->last_byte == EOF)
return -1;
return hpgs_reader_check_param_end(reader);
}
/*
HPGL command LB (LaBel)
*/
int hpgs_reader_do_LB (hpgs_reader *reader)
{
char str[HPGS_MAX_LABEL_SIZE];
double w,h,ca,sa;
hpgs_point left_vec;
hpgs_point up_vec;
hpgs_point space_vec;
hpgs_point lf_vec;
hpgs_point adj_vec;
int i0=0;
int ipos=0;
int i;
if (hpgs_reader_read_label_string(reader,str)) return -1;
if (hpgs_reader_checkpath(reader)) return -1;
w =
reader->current_char_size.x ? (1.5 * reader->current_char_size.x) :
(72.0 / (reader->alternate_font ?
reader->alternate_pitch :
reader->default_pitch ));
h =
reader->current_char_size.y ? reader->current_char_size.y :
(reader->alternate_font ?
reader->alternate_height :
reader->default_height );
ca = cos(reader->current_label_angle);
sa = sin(reader->current_label_angle);
left_vec.x = ca * w;
left_vec.y = sa * w;
up_vec.x = (reader->current_slant * ca - sa) * h;
up_vec.y = (reader->current_slant * sa + ca) * h;
switch (reader->current_text_path % 4)
{
case 0:
space_vec.x = ca * (1.0+reader->current_extra_space.x) * w;
space_vec.y = sa * (1.0+reader->current_extra_space.x) * w;
lf_vec.x = sa * (HPGS_LF_FAC+reader->current_extra_space.y) * h;
lf_vec.y = -ca * (HPGS_LF_FAC+reader->current_extra_space.y) * h;
adj_vec.x = sa * h;
adj_vec.y = -ca * h;
break;
case 1:
space_vec.x = sa * (HPGS_VSPACE_FAC+reader->current_extra_space.y) * h;
space_vec.y = -ca * (HPGS_VSPACE_FAC+reader->current_extra_space.y) * h;
lf_vec.x = -ca * (HPGS_LF_FAC+reader->current_extra_space.x) * w;
lf_vec.y = -sa * (HPGS_LF_FAC+reader->current_extra_space.x) * w;
adj_vec.x = -ca * w;
adj_vec.y = -sa * w;
break;
case 2:
space_vec.x = -ca * (1.0+reader->current_extra_space.x) * w;
space_vec.y = -sa * (1.0+reader->current_extra_space.x) * w;
lf_vec.x = -sa * (HPGS_LF_FAC+reader->current_extra_space.y) * h;
lf_vec.y = ca * (HPGS_LF_FAC+reader->current_extra_space.y) * h;
adj_vec.x = -sa * h;
adj_vec.y = ca * h;
break;
default: // 3
space_vec.x = -sa * (HPGS_VSPACE_FAC+reader->current_extra_space.y) * h;
space_vec.y = ca * (HPGS_VSPACE_FAC+reader->current_extra_space.y) * h;
lf_vec.x = ca * (HPGS_LF_FAC+reader->current_extra_space.x) * w;
lf_vec.y = sa * (HPGS_LF_FAC+reader->current_extra_space.x) * w;
adj_vec.x = ca * w;
adj_vec.y = sa * w;
}
if (reader->current_text_line)
{
lf_vec.x = -lf_vec.x;
lf_vec.y = -lf_vec.y;
}
hpgs_matrix_scale(&left_vec, &reader->page_matrix,&left_vec );
hpgs_matrix_scale(&up_vec, &reader->page_matrix,&up_vec );
hpgs_matrix_scale(&space_vec,&reader->page_matrix,&space_vec);
hpgs_matrix_scale(&lf_vec, &reader->page_matrix,&lf_vec );
hpgs_matrix_scale(&adj_vec, &reader->page_matrix,&adj_vec );
hpgs_point adj = { 0.0, 0.0 };
// got through the string and search for control characters.
for (i=0;i<=HPGS_MAX_LABEL_SIZE;i++)
{
if (i < HPGS_MAX_LABEL_SIZE && (unsigned char)str[i] >= 32)
{
if (ipos == 0 && reader->current_label_origin % 10 > 1)
{
// Everytime we start a new portion of the label,
// adapt the current point in order to meet the given label origin.
// lookahead for the new CR of EOS.
int j;
double x_adj,y_adj,nchars=0.0;
for (j=i;j<=HPGS_MAX_LABEL_SIZE;j++)
{
if (j < HPGS_MAX_LABEL_SIZE && (unsigned char)str[j] >= 32)
nchars+=1.0;
else
if (j >= HPGS_MAX_LABEL_SIZE || str[j] == 0 || str[j] == 13) break;
}
if (nchars && (reader->current_text_path % 2))
nchars -= reader->current_extra_space.y / (1.0 + reader->current_extra_space.y);
else
nchars -= reader->current_extra_space.x / (1.0 + reader->current_extra_space.x);
x_adj = -0.5 * nchars * ((reader->current_label_origin % 10 - 1) / 3);
y_adj = -0.5 * ((reader->current_label_origin % 10 - 1) % 3);
if (reader->current_label_origin / 10)
{
x_adj -= 0.25 * ((reader->current_label_origin % 10 - 1) / 3 - 1);
y_adj -= 0.25 * ((reader->current_label_origin % 10 - 1) % 3 - 1);
}
adj.x += x_adj * space_vec.x - y_adj * adj_vec.x;
adj.y += x_adj * space_vec.y - y_adj * adj_vec.y;
}
if (ipos == 0)
switch (reader->current_text_path % 4)
{
case 1:
adj.x -= up_vec.x;
adj.y -= up_vec.y;
break;
case 2:
adj.x -= left_vec.x + up_vec.x;
adj.y -= left_vec.y + up_vec.y;
break;
case 3:
adj.x -= left_vec.x;
adj.y -= left_vec.y;
}
++ipos;
continue;
}
reader->current_point.x += adj.x;
reader->current_point.y += adj.y;
if (i>i0 &&
hpgs_reader_label(reader,str+i0,i-i0,
reader->alternate_font ?
reader->alternate_face :
reader->default_face,
reader->alternate_font ?
reader->alternate_encoding :
reader->default_encoding,
reader->alternate_font ?
reader->alternate_posture :
reader->default_posture,
reader->alternate_font ?
reader->alternate_weight :
reader->default_weight,
&left_vec,
&up_vec,
&space_vec))
return -1;
reader->current_point.x -= adj.x;
reader->current_point.y -= adj.y;
adj.x = 0.0;
adj.y = 0.0;
if (i >= HPGS_MAX_LABEL_SIZE || str[i] == 0) break;
i0 = i+1;
switch (str[i])
{
case 8: // backspace
reader->current_point.x -= space_vec.x;
reader->current_point.y -= space_vec.y;
break;
case 9: // horizontal tab.
reader->current_point.x += space_vec.x * (8 - ipos % 8);
reader->current_point.y += space_vec.y * (8 - ipos % 8);
ipos += (8 - ipos % 8);
break;
case 10: // linefeed.
reader->cr_point.x += lf_vec.x;
reader->cr_point.y += lf_vec.y;
reader->current_point.x += lf_vec.x;
reader->current_point.y += lf_vec.y;
break;
case 13: // carriage return.
reader->current_point.x = reader->cr_point.x;
reader->current_point.y = reader->cr_point.y;
ipos=0;
break;
case 14: // shift out.
reader->alternate_font = 1;
break;
case 15: // shift in.
reader->alternate_font = 0;
break;
default:
if (reader->verbosity >= 1)
hpgs_log(hpgs_i18n("LB: Ignoring unknown control character <%d>.\n"),
(int)str[i]);
}
}
return 0;
}
/*
HPGL command MG (MessaGe)
*/
int hpgs_reader_do_MG (hpgs_reader *reader)
{
char str[HPGS_MAX_LABEL_SIZE];
if (reader->eoc) return 0;
if (hpgs_reader_read_new_string(reader,str)) return -1;
if (reader->verbosity >= 1)
hpgs_log(hpgs_i18n("Message <%.*s>.\n"),HPGS_MAX_LABEL_SIZE,str);
return 0;
}

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,151 @@
/***********************************************************************
* *
* $Id: hpgsdevices.h 298 2006-03-05 18:18:03Z softadm $
* *
* hpgs - HPGl Script, a hpgl/2 interpreter, which uses a Postscript *
* API for rendering a scene and thus renders to a variety of *
* devices and fileformats. *
* *
* (C) 2004-2006 ev-i Informationstechnologie GmbH http://www.ev-i.at *
* *
* Author: Wolfgang Glas *
* *
* hpgs is free software; you can redistribute it and/or *
* modify it under the terms of the GNU Lesser General Public *
* License as published by the Free Software Foundation; either *
* version 2.1 of the License, or (at your option) any later version. *
* *
* hpgs is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU *
* Lesser General Public License for more details. *
* *
* You should have received a copy of the GNU Lesser General Public *
* License along with this library; if not, write to the *
* Free Software Foundation, Inc., 59 Temple Place, Suite 330, *
* Boston, MA 02111-1307 USA *
* *
***********************************************************************
* *
* The private interfaces for the basic devices *
* *
***********************************************************************/
#ifndef __HPGS_DEVICES_H
#define __HPGS_DEVICES_H
#include<hpgs.h>
#ifdef __cplusplus
extern "C" {
#endif
/*! \file hpgsdevices.h
\brief The private interfaces for basic vector devices.
A header file, which declares the structures and functions internally
used for implementing the very basic implementations of \c hpgs_device.
*/
/*! @addtogroup device
* @{
*/
#define HPGS_PLOTSIZE_MAX_CLIP_DEPTH 16
/*! \brief A vector graphics device for plotsize calculating.
This structure implements a \c hpgs_device and is used to calculate
the bounding box of a vector graphics scenery.
*/
struct hpgs_plotsize_device_st {
hpgs_device inherited; //!< The base device structure.
hpgs_bool ignore_ps; //!< Do we ignore a PS command?
int clip_depth; //!< The depth of the current clip path stack.
hpgs_point moveto; //!< The position of the last moveto.
int deferred_moveto; //!< Do we have an unregistered moveto pending?
hpgs_bool do_linewidth; //!< Do we account for the current linewidth?
double linewidth; //!< Current linewidth.
hpgs_bbox clip_bbs[HPGS_PLOTSIZE_MAX_CLIP_DEPTH]; /*! The bounding boxes of the clip paths. */
hpgs_bbox path_bb; /*! The bounding box of the current path. */
hpgs_bbox page_bb; /*! The bounding box of the current page. */
hpgs_bbox global_bb; /*! The currently calculated overall bounding box. */
/*@{ */
/*! A stack of page bounding boxes.
*/
hpgs_bbox *page_bbs; /*! The currently calculated overall bounding box. */
int n_page_bbs;
int page_bbs_alloc_size;
/*@} */
};
typedef struct hpgs_ps_media_size_st hpgs_ps_media_size;
/*! \brief A structure for storing a paper size.
This structure stores a PostScipt paper size.
*/
struct hpgs_ps_media_size_st
{
int width; //!< The width of the paper in pt.
int height; //!< The height of the paper in pt.
const char *name; //!< The name of this paper size, if it is a std paper size.
size_t usage; //!< The usage count of this paper size.
size_t hash; //!< A hash value for storing media sizes in a sorted vector.
};
/*! \brief A vector graphics device for drawing to an eps file.
This structure implements a \c hpgs_device and is used to write
a scenery to an eps file.
*/
struct hpgs_eps_device_st {
hpgs_device inherited; //!< The base device structure.
hpgs_bbox doc_bb;
/*! The document bounding box used for multipage postscript files. */
hpgs_bbox page_bb;
/*! The bounding box of the current page. */
int n_pages;
/*! The number of pages. -1...we are writing individual eps files. */
char *filename; //!< The output filename.
hpgs_ostream *out; //!< The current page stream.
hpgs_bool page_setup; //!< Is the current page set up?
/*@{ */
/*! A stack of media sizes for multipage PostScript files.
The media sizes are sorted by their hash value.
*/
hpgs_ps_media_size *media_sizes; /*! The currently calculated overall bounding box. */
int n_media_sizes;
int media_sizes_alloc_size;
/*@} */
hpgs_xrop3_func_t rop3; //!< The ROP3 transfer raster operation.
hpgs_palette_color pattern_color; //!< The color of the ROP3 pattern.
hpgs_color color; //!< The current output color.
};
HPGS_INTERNAL_API void hpgs_cleanup_plugin_devices();
/*! @} */ /* end of group device */
#ifdef __cplusplus
} // end of extern "C"
#endif
#endif /* ! __HPGS_DEVICES_H */

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,296 @@
/***********************************************************************
* *
* $Id: hpgsfont.h 307 2006-03-07 08:45:04Z softadm $
* *
* hpgs - HPGl Script, a hpgl/2 interpreter, which uses a Postscript *
* API for rendering a scene and thus renders to a variety of *
* devices and fileformats. *
* *
* (C) 2004-2006 ev-i Informationstechnologie GmbH http://www.ev-i.at *
* *
* Author: Wolfgang Glas *
* *
* hpgs is free software; you can redistribute it and/or *
* modify it under the terms of the GNU Lesser General Public *
* License as published by the Free Software Foundation; either *
* version 2.1 of the License, or (at your option) any later version. *
* *
* hpgs is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU *
* Lesser General Public License for more details. *
* *
* You should have received a copy of the GNU Lesser General Public *
* License along with this library; if not, write to the *
* Free Software Foundation, Inc., 59 Temple Place, Suite 330, *
* Boston, MA 02111-1307 USA *
* *
***********************************************************************
* *
* Private header file for ttf font support. *
* *
***********************************************************************/
#ifndef __HPGS_FONT_H__
#define __HPGS_FONT_H__
#include<hpgsmutex.h>
#include<stdint.h>
HPGS_INTERNAL_API void hpgs_font_init();
HPGS_INTERNAL_API void hpgs_font_cleanup();
// The max. number of ttf tables to store.
#define HPGS_FONT_MAX_TTF_TABLES 32
typedef struct hpgs_font_header_st hpgs_font_header;
typedef struct hpgs_font_dentry_st hpgs_font_dentry;
typedef struct hpgs_font_table_entry_st hpgs_font_table_entry;
typedef struct hpgs_font_head_data_st hpgs_font_head_data;
typedef struct hpgs_font_hhea_data_st hpgs_font_hhea_data;
typedef struct hpgs_font_maxp_data_st hpgs_font_maxp_data;
typedef struct hpgs_font_longHorMetrics_st hpgs_font_longHorMetrics;
typedef struct hpgs_font_cmap_data_st hpgs_font_cmap_data;
typedef struct hpgs_font_cmap_code_range_st hpgs_font_cmap_code_range;
typedef struct hpgs_font_post_data_st hpgs_font_post_data;
typedef struct hpgs_font_glyph_point_st hpgs_font_glyph_point;
typedef struct hpgs_font_glyph_ref_st hpgs_font_glyph_ref;
typedef struct hpgs_font_glyph_data_st hpgs_font_glyph_data;
typedef struct hpgs_font_kern_pair_st hpgs_font_kern_pair;
struct hpgs_font_table_entry_st
{
uint32_t tag; /* Table name */
uint32_t checksum; /* for table */
uint32_t offset; /* to start of table in input file */
uint32_t length; /* length of table */
};
struct hpgs_font_head_data_st {
uint32_t version;
uint32_t fontRevision;
uint32_t checkSumAdjustment;
uint32_t magicNumber;
uint16_t flags;
uint16_t unitsPerEm;
//int64_t created;
//int64_t modified;
int32_t created_low;
int32_t created_high;
int32_t modified_low;
int32_t modified_high;
int16_t xMin;
int16_t yMin;
int16_t xMax;
int16_t yMax;
uint16_t macStyle;
int16_t lowestRecPPEM;
int16_t fontDirectionHint;
int16_t indexToLocFormat;
int16_t glyphDataFormat;
};
struct hpgs_font_hhea_data_st {
uint32_t version;
int16_t ascent;
int16_t descent;
int16_t lineGap;
uint16_t advanceWidthMax;
int16_t minLeftSideBearing;
int16_t minRightSideBearing;
int16_t xMaxExtent;
int16_t caretSlopeRise;
int16_t caretSlopeRun;
int16_t caretOffset;
int16_t reserved1;
int16_t reserved2;
int16_t reserved3;
int16_t reserved4;
int16_t metricDataFormat;
uint16_t numOfLongHorMetrics;
};
struct hpgs_font_maxp_data_st {
uint32_t version;
uint16_t numGlyphs;
uint16_t maxPoints;
uint16_t maxContours;
uint16_t maxComponentPoints;
uint16_t maxComponentContours;
uint16_t maxZones;
uint16_t maxTwilightPoints;
uint16_t maxStorage;
uint16_t maxFunctionDefs;
uint16_t maxInstructionDefs;
uint16_t maxStackElements;
uint16_t maxSizeOfInstructions;
uint16_t maxComponentElements;
uint16_t maxComponentDepth;
};
struct hpgs_font_longHorMetrics_st
{
uint16_t advanceWidth;
int16_t leftSideBearing;
};
struct hpgs_font_cmap_code_range_st
{
uint16_t startCode;
uint16_t endCode;
uint16_t idDelta;
uint16_t idRangeOffset;
};
struct hpgs_font_cmap_data_st
{
size_t ranges_sz;
hpgs_font_cmap_code_range *ranges;
size_t glyphIndexArray_sz;
uint16_t *glyphIndexArray;
};
struct hpgs_font_post_data_st
{
int32_t version; // 0x00020000 for version 2.0
int32_t italicAngle; // Italic angle in counter-clockwise degrees from the vertical. Zero for upright text, negative for text that leans to the right (forward).
int16_t underlinePosition; // This is the suggested distance of the top of the underline from the baseline (negative values indicate below baseline).
int16_t underlineThickness; // Suggested values for the underline thickness.
uint32_t isFixedPitch; // Set to 0 if the font is proportionally spaced, non-zero if the font is not proportionally spaced (i.e. monospaced).
uint32_t minMemType42; // Minimum memory usage when an OpenType font is downloaded.
uint32_t maxMemType42; // Maximum memory usage when an OpenType font is downloaded.
uint32_t minMemType1; // Minimum memory usage when an OpenType font is downloaded as a Type 1 font.
uint32_t maxMemType1; // Maximum memory usage when an OpenType font is downloaded as a Type 1 font.
uint16_t numberOfGlyphs; // Number of glyphs (this should be the same as numGlyphs in 'maxp' table).
const char **names; // pointer to the glyph names.
const char *name_data; // the buffer holding the actual data.
};
#define HPGS_FONT_GLYPH_POINT_START 1
#define HPGS_FONT_GLYPH_POINT_ONCURVE 2
#define HPGS_FONT_GLYPH_POINT_CONTROL 3
struct hpgs_font_glyph_point_st
{
hpgs_point p;
int flags; // HPGS_FONT_GLYPH_POINT_*
};
struct hpgs_font_glyph_ref_st
{
hpgs_matrix matrix; // transformation matrix
uint16_t gid; // the references glyph id.
};
struct hpgs_font_glyph_data_st
{
hpgs_bbox bbox;
size_t points_sz;
hpgs_font_glyph_point *points;
size_t refs_sz;
size_t refs_alloc_sz;
hpgs_font_glyph_ref *refs;
size_t begin_kern_pair; /*!< The index of the first kern pair where this glyph id the left one. */
size_t end_kern_pair;/*!< The index of the first kern pair after \c begin_kern_pair where this glyph id is not the left one. */
};
/*!
\brief A ttf kerning pair
*/
struct hpgs_font_kern_pair_st
{
uint16_t left_gid; /*!< The left glyph ID. */
uint16_t right_gid; /*!< The rightt glyph ID. */
double value; /*!< The correction of the advynce width in em. */
};
/*! \brief A truetype font header.
This structure holds all the header information of a truetype font
and is used when scanning a fon directory as well as a part of an
open font file.
*/
struct hpgs_font_header_st
{
int32_t version; /*!< 0x00010000 */
uint16_t numtab; /*!< The number truetype tables in this file. */
uint16_t searchRange; /*!< (Max power of 2 <= numtab) *16 */
uint16_t entrySel; /*!< Log2(Max power of 2 <= numtab ) */
uint16_t rangeShift; /*!< numtab*16 - searchRange */
hpgs_font_table_entry tables[HPGS_FONT_MAX_TTF_TABLES]; /*!< The truetype table entries. */
int name_table; /*!< The position of the name table. */
int head_table; /*!< The position of the head table. */
int hhea_table; /*!< The position of the hhea table. */
int maxp_table; /*!< The position of the maxp table. */
int hmtx_table; /*!< The position of the hmtx table. */
int loca_table; /*!< The position of the loca table. */
int cmap_table; /*!< The position of the cmap table. */
int post_table; /*!< The position of the post table. */
int glyf_table; /*!< The position of the glyf table. */
int kern_table; /*!< The position of the kern table. */
};
/*! \brief A truetype font.
This structure holds all details for operating on a truetype font
file. The font file is kept open by the font object during it's
lifetime, since we operate on the font file like on a database.
*/
struct hpgs_font_st
{
hpgs_istream *is; /*!< The input stream to operate on. */
// the file header.
hpgs_font_header header;
hpgs_font_head_data head_data; /*!< The head table. */
hpgs_font_hhea_data hhea_data; /*!< The hhea table. */
hpgs_font_maxp_data maxp_data; /*!< The maxp table. */
hpgs_font_longHorMetrics *hmtx_data;
/*!< The hmtx table. This array has a dimension of maxp_data.numGlyphs. */
uint32_t *loca_data; /*!< The loca table. */
size_t loca_data_sz; /*!< The size of the loca table. */
hpgs_font_cmap_data cmap_data; /*!< The cmap table. */
hpgs_font_post_data post_data; /*!< The post table. */
hpgs_font_kern_pair *kern_data;
size_t kern_data_sz; /*!< The size of the kern table. */
int *glyph_cache_positions;
/*!< The position of an individual glyph in \c glyph_cache or -1, if the glyph has not been cached yet.
This array has a dimension of maxp_data.numGlyphs
*/
size_t n_cached_glyphs; /*!< The number of actually cached glyphs. */
hpgs_font_glyph_data *glyph_cache; /*!< The cached glyphs. This array has a dimension of maxp_data.numGlyphs. */
hpgs_mutex_t mutex; /*!< The mutex to protec glyph access and reference counting. */
size_t nref; /*!< The reference count. */
};
/*! \brief A truetype font directory entry.
This structure holds an entry in the font directory.
*/
struct hpgs_font_dentry_st {
char *font_name; /*!< The utf8-encoded name of the font. */
char *filename; /*!< The filename of the font. */
hpgs_font *font; /*!< The font object, if this font is cached. */
};
#endif

View File

@ -0,0 +1,629 @@
/***********************************************************************
* *
* $Id: hpgsglobal.c 338 2006-06-17 08:33:36Z softadm $
* *
* hpgs - HPGl Script, a hpgl/2 interpreter, which uses a Postscript *
* API for rendering a scene and thus renders to a variety of *
* devices and fileformats. *
* *
* (C) 2004-2006 ev-i Informationstechnologie GmbH http://www.ev-i.at *
* *
* Author: Wolfgang Glas *
* *
* hpgs is free software; you can redistribute it and/or *
* modify it under the terms of the GNU Lesser General Public *
* License as published by the Free Software Foundation; either *
* version 2.1 of the License, or (at your option) any later version. *
* *
* hpgs is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU *
* Lesser General Public License for more details. *
* *
* You should have received a copy of the GNU Lesser General Public *
* License along with this library; if not, write to the *
* Free Software Foundation, Inc., 59 Temple Place, Suite 330, *
* Boston, MA 02111-1307 USA *
* *
***********************************************************************
* *
* Global resources of HPGS. *
* *
***********************************************************************/
#include <hpgsdevices.h>
#include <hpgsreader.h>
#include <hpgsfont.h>
#include <hpgsi18n.h>
#include <math.h>
#include <string.h>
#include <ctype.h>
#include <errno.h>
#ifdef WIN32
#include <windows.h>
static DWORD tls_handle = -1;
/* Use a separate heap for the error messages. This heap is
destroyed in hpgs_cleanup, so we risk no lost pointers. */
static HANDLE hHeap = 0;
/*! A counterpart of vsprintf, which allocates the result string
on the heap an is save against buffer overflows.
Returns 0, if the system is out of memory.
*/
static char* vsprintf_hHeap (const char *fmt, va_list ap)
{
/* Guess we need no more than 1024 bytes. */
int n, size = 1024;
char *p;
if ((p = HeapAlloc (hHeap,0,size)) == NULL)
return p;
while (1)
{
/* Try to print in the allocated space. */
n = _vsnprintf (p, size, fmt, ap);
/* If that worked, return the string. */
if (n > -1 && n < size)
{ return p; }
/* Else try again with more space. */
if (n > -1) /* glibc 2.1 */
size = n+1; /* precisely what is needed */
else /* glibc 2.0 */
size *= 2; /* twice the old size */
{
char *np = HeapReAlloc (hHeap,0,p,size);
if (!np) { HeapFree(hHeap,0,p); return 0; }
p = np;
}
}
}
static char* sprintf_hHeap (const char *fmt, ...)
{
va_list ap;
char *ret;
va_start(ap, fmt);
ret = vsprintf_hHeap(fmt,ap);
va_end(ap);
return ret;
}
#else
#include <pthread.h>
static pthread_key_t key;
#endif
static char *hpgs_reader_prefix=0;
/*! This function has to be called before using any other
function of hpgs. It defines the path, where additional
files such as the truetype files for HPGL files or plugins
are stored.
Truetype fonts are searched in the path <prefix>/share/hpgs
The path is internally duplicated using \c strdup.
*/
void hpgs_init(const char *path)
{
int l;
hpgs_reader_prefix = strdup(path);
if (!hpgs_reader_prefix) return;
// strip off trailing directory separators.
l = strlen(hpgs_reader_prefix);
if (l && hpgs_reader_prefix[l-1] == HPGS_PATH_SEPARATOR)
hpgs_reader_prefix[l-1] = '\0';
#ifdef WIN32
hHeap = HeapCreate(0,4096,128*1024);
tls_handle = TlsAlloc();
#else
pthread_key_create (&key,free);
#endif
#ifdef HPGS_HAVE_GETTEXT
hpgs_i18n_init();
#endif
hpgs_font_init();
}
/*! This function return a pointer to the installation prefix
set through \c hpgs_init. The returned string has any trailing
directory separator of the string passed to \c hpgs_init stripped
off.
*/
HPGS_API const char *hpgs_get_prefix()
{
if (hpgs_reader_prefix)
return hpgs_reader_prefix;
#ifdef WIN32
return "C:\\Programme\\EV-i";
#else
#ifndef HPGS_DEFAULT_PREFIX
return "/usr/local";
#else
return HPGS_DEFAULT_PREFIX;
#endif
#endif
}
/*! This function has to be called atfer the last usage of hpgs.
It cleans up internally allocated resources.
*/
void hpgs_cleanup()
{
hpgs_font_cleanup();
hpgs_cleanup_plugin_devices();
if (hpgs_reader_prefix)
{
free(hpgs_reader_prefix);
hpgs_reader_prefix = 0;
}
#ifdef WIN32
TlsFree(tls_handle);
HeapDestroy(hHeap);
hHeap=0;
tls_handle=-1;
#else
hpgs_clear_error();
pthread_key_delete (key);
#endif
}
/*! Get the value of the command line argument argv[0],
if the argument starts with \c opt.
This subroutine is useful when parsing command lines
like in the following loop:
\verbatim
int main(int argc, const char *argv[])
{
while (argc>1)
{
int narg = 1;
const char *value;
if (hpgs_get_arg_value("-r",argv,&value,&narg))
{
...parse value of option -r...
}
else if (hpgs_get_arg_value("-p",argv,&value,&narg))
{
...parse value of option -p...
}
else
{
if (argv[0][0] == '-')
{
fprintf(stderr,"Error: Unknown option %s given.\n",argv[0]);
return usage();
}
break;
}
argv+=narg;
argc-=narg;
}
\endverbatim
Returns \c HPGS_TRUE, if argv[0] starts with opt.
If \c *narg == 2, argv[0] is exactly \c opt and
\c *value points to \c argv[1].
If \c *narg == 1, argv[0] startwith \c opt and
\c *value points to \c argv[0]+strlen(opt).
Returns \c HPGS_FALSE, if argv[0] does not start with \c opt.
*/
hpgs_bool hpgs_get_arg_value(const char *opt, const char *argv[],
const char **value, int *narg)
{
int l = strlen(opt);
if (strncmp(opt,argv[0],l)!=0)
return 0;
if (l == strlen(argv[0]))
{
*value = argv[1];
*narg = 2;
}
else
{
*value = argv[0] + l;
*narg = 1;
}
return 1;
}
/*! This subroutine encapsulates the standard C library function \c realloc.
This is needed in order to aviod hassels when \c realloc returns
a null pointer and the original pointer is still needed for subsequent
deallocations.
\c itemsz is the size of the individual items in the array.
\c pptr is a pointer to the pointer holding te address of the array.
On success, \c *pptr points to the newly allocated array, otherwise
\c *pptr is untouched.
\c psz is a pointer to the allocated size of the array .
On success, *psz hold the new size \c nsz of the array,
otherwise \c *psz is untouched.
Returns 0 upon success or -1 if the system is out of memory.
*/
int hpgs_array_safe_resize (size_t itemsz, void **pptr, size_t *psz, size_t nsz)
{
void *np = realloc(*pptr,nsz*itemsz);
if (!np) return -1;
*pptr=np;
*psz=nsz;
return 0;
}
/*! A counterpart of vsprintf, which allocates the result string
on the heap an is save against buffer overflows.
Returns 0, if the system is out of memory.
*/
char* hpgs_vsprintf_malloc (const char *fmt, va_list ap)
{
/* Guess we need no more than 1024 bytes. */
int n, size = 1024;
char *p;
if ((p = malloc (size)) == NULL)
return p;
while (1)
{
/* Try to print in the allocated space. */
va_list aq;
va_copy(aq, ap);
#ifdef WIN32
n = _vsnprintf (p, size, fmt, aq);
#else
n = vsnprintf (p, size, fmt, aq);
#endif
va_end(aq);
/* If that worked, return the string. */
if (n > -1 && n < size)
{ return p; }
/* Else try again with more space. */
if (n > -1) /* glibc 2.1 */
size = n+1; /* precisely what is needed */
else /* glibc 2.0 */
size *= 2; /* twice the old size */
{
char *np = realloc (p, size);
if (!np) { free(p); return 0; }
p = np;
}
}
}
/*! A counterpart of sprintf, which allocates the result string
on the heap an is save against buffer overflows.
Returns 0, if the system is out of memory.
*/
char* hpgs_sprintf_malloc (const char *fmt, ...)
{
va_list ap;
char *ret;
va_start(ap, fmt);
ret = hpgs_vsprintf_malloc(fmt,ap);
va_end(ap);
return ret;
}
/*! Constructs a filename on the heap for a file located in the
installation path passed to \c hpgs_init.
Returns 0, if the system is out of memory.
*/
char *hpgs_share_filename(const char *rel_filename)
{
return hpgs_sprintf_malloc("%s%cshare%chpgs%c%s",
hpgs_get_prefix(),
HPGS_PATH_SEPARATOR,
HPGS_PATH_SEPARATOR,
HPGS_PATH_SEPARATOR,
rel_filename);
}
/*! Set the error message of the current thread to the given string.
Always returns -1.
*/
int hpgs_set_error(const char *fmt, ...)
{
va_list ap;
int ret;
va_start(ap, fmt);
ret = hpgs_set_verror(fmt,ap);
va_end(ap);
return ret;
}
/*! Prepends the error message of the current thread with the given string.
this is useful, if you want to push context information
to the error message.
Always returns -1.
*/
int hpgs_error_ctxt(const char *fmt, ...)
{
va_list ap;
int ret;
va_start(ap, fmt);
ret = hpgs_verror_ctxt(fmt,ap);
va_end(ap);
return ret;
}
/*! Set the error message of the current thread to the given string.
Always returns -1.
*/
int hpgs_set_verror(const char *fmt, va_list ap)
{
char *x;
#ifdef WIN32
x = (char *)TlsGetValue(tls_handle);
if (x) HeapFree(hHeap,0,x);
x = vsprintf_hHeap(fmt,ap);
TlsSetValue(tls_handle,x);
#else
x = (char *)pthread_getspecific (key);
if (x) free(x);
va_list aq;
va_copy(aq, ap);
x = hpgs_vsprintf_malloc(fmt,aq);
va_end(aq);
pthread_setspecific (key,x);
#endif
return -1;
}
/*!
Clears the error message of the current thread.
*/
void hpgs_clear_error()
{
char *x;
#ifdef WIN32
x = (char *)TlsGetValue(tls_handle);
if (x) HeapFree(hHeap,0,x);
TlsSetValue(tls_handle,0);
#else
x = (char *)pthread_getspecific (key);
if (x) free(x);
pthread_setspecific (key,0);
#endif
}
/*!
Checks, whther the error message of the current thread has been set.
*/
HPGS_API hpgs_bool hpgs_have_error()
{
char *x;
#ifdef WIN32
x = (char *)TlsGetValue(tls_handle);
#else
x = (char *)pthread_getspecific (key);
#endif
return x != 0;
}
/*! Prepends the error message of the current thread with the given string.
this is useful, if you want to push context information
to the error message.
Always returns -1.
*/
int hpgs_verror_ctxt(const char *fmt, va_list ap)
{
char *x;
#ifdef WIN32
x = (char *)TlsGetValue(tls_handle);
if (!fmt) return -1;
char * new_p = vsprintf_hHeap(fmt,ap);
if (!new_p) return -1;
if (x)
{
char *tmp = sprintf_hHeap("%s: %s",new_p,x);
HeapFree(hHeap,0,new_p);
if (!tmp) return -1;
HeapFree(hHeap,0,x);
new_p = tmp;
}
TlsSetValue(tls_handle,new_p);
#else
x = (char *)pthread_getspecific (key);
char * new_p = hpgs_vsprintf_malloc(fmt,ap);
if (!new_p) return -1;
if (x)
{
char *tmp = hpgs_sprintf_malloc("%s: %s",new_p,x);
free(new_p);
if (!tmp) return -1;
free(x);
new_p = tmp;
}
pthread_setspecific (key,new_p);
#endif
return -1;
}
/*!
Get the error message of the current thread.
*/
const char *hpgs_get_error()
{
const char *ret;
#ifdef WIN32
ret = (char *)TlsGetValue(tls_handle);
#else
ret = (char *)pthread_getspecific (key);
#endif
if (!ret) ret = hpgs_i18n("(no error)");
return ret;
}
static void default_hpgs_logger(const char *fmt, va_list ap)
{
va_list aq;
va_copy(aq, ap);
vfprintf(stderr,fmt,aq);
va_end(ap);
}
static hpgs_logger_func_t static_logger = default_hpgs_logger;
/*!
Set the logging function for logging informational messages.
If \c func is NULL, the default logging function, which log to
\c stderr is restored.
Warning: This function is not thread-safe and should be called
just after \c hpgs_init() at the beginning of the program.
*/
void hpgs_set_logger(hpgs_logger_func_t func)
{
if (func)
static_logger = func;
else
static_logger = default_hpgs_logger;
}
/*!
Logs an informational message using the function set with
\c hpgs_set_logger(). If no function is set with \c hpgs_set_logger(),
the message is printed to \c stderr.
*/
void hpgs_log(const char *fmt, ...)
{
va_list ap;
va_start(ap, fmt);
static_logger(fmt,ap);
va_end(ap);
}
/*!
Logs an informational message using the function set with
\c hpgs_set_logger(). If no function is set with \c hpgs_set_logger(),
the message is printed to \c stderr.
*/
void hpgs_vlog(const char *fmt, va_list ap)
{
va_list aq;
va_copy(aq, ap);
static_logger(fmt,aq);
va_end(aq);
}
/*!
Returns the character code at the given position in an utf-8 string.
The pointer \c (*p) is advanced to the next character after the current
position.
*/
int hpgs_next_utf8(const char **p)
{
int ret;
if (((unsigned char)**p & 0x80) == 0)
ret = **p;
else
{
// Hit in the middle of a multibyte sequence
// -> return EOS.
if (((unsigned char)**p & 0xC0) == 0x80)
ret = 0;
else
{
// true multibyte sequence
int mask = 0x20;
int need = 2;
ret = 0x1f;
while (**p & mask)
{ ret >>= 1; mask >>=1; ++need; }
ret &= **p;
while (--need)
{
++(*p);
if (((**p) & 0xc0) != 0x80) { return 0; }
ret = (ret << 6) | ((**p) & 0x3f);
}
}
}
++(*p);
return ret;
}
/*!
Returns the number of unicode characters contained in the first \c n bytes
of the given utf-8 string. If the null character is encountered, the
interpretation is stopped before the n'th byte.
if \c n == -1, the string is ultimatively search up to the first occurrence
of the null character.
The pointer \c (*p) is advanced to the next character after the current
position.
*/
HPGS_API int hpgs_utf8_strlen(const char *p, int n)
{
const char **pp = &p;
int ret = 0;
while ((n<0 || ((*pp) - p) < n) && hpgs_next_utf8(pp) != 0)
++ret;
return ret;
}

View File

@ -0,0 +1,112 @@
/***********************************************************************
* *
* $Id: hpgsgstate.c 270 2006-01-29 21:12:23Z softadm $
* *
* hpgs - HPGl Script, a hpgl/2 interpreter, which uses a Postscript *
* API for rendering a scene and thus renders to a variety of *
* devices and fileformats. *
* *
* (C) 2004-2006 ev-i Informationstechnologie GmbH http://www.ev-i.at *
* *
* Author: Wolfgang Glas *
* *
* hpgs is free software; you can redistribute it and/or *
* modify it under the terms of the GNU Lesser General Public *
* License as published by the Free Software Foundation; either *
* version 2.1 of the License, or (at your option) any later version. *
* *
* hpgs is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU *
* Lesser General Public License for more details. *
* *
* You should have received a copy of the GNU Lesser General Public *
* License along with this library; if not, write to the *
* Free Software Foundation, Inc., 59 Temple Place, Suite 330, *
* Boston, MA 02111-1307 USA *
* *
***********************************************************************
* *
* The implementation of the public API for the gstate. *
* *
***********************************************************************/
#include<hpgspaint.h>
#include<assert.h>
#include<string.h>
/*! Creates a new gstate on the heap.
Use \c hpgs_gstate_destroy in order to destroy the returned
gstate pointer.
A null pointer is returned, if the system is out of memory.
*/
hpgs_gstate *hpgs_new_gstate()
{
hpgs_gstate *ret = (hpgs_gstate *)malloc(sizeof(hpgs_gstate));
if (ret)
{
ret->line_cap = hpgs_cap_butt;
ret->line_join = hpgs_join_miter;
ret->color.r = 0.0;
ret->color.g = 0.0;
ret->color.b = 0.0;
ret->miterlimit = 5.0;
ret->linewidth = 1.0;
ret->n_dashes = 0;
ret->dash_lengths = 0;
ret->dash_offset = 0.0;
// ROP3 function: destination = source or pattern.
ret->rop3 = 252;
ret->src_transparency = HPGS_TRUE;
ret->pattern_transparency = HPGS_TRUE;
ret->pattern_color.r = 0.0;
ret->pattern_color.g = 0.0;
ret->pattern_color.b = 0.0;
}
return ret;
}
/*! Destroys a gstate created using \c hpgs_new_gstate.
*/
void hpgs_gstate_destroy(hpgs_gstate *gstate)
{
if (!gstate) return;
if (gstate->dash_lengths) free(gstate->dash_lengths);
free (gstate);
}
/*! Sets the dashes of \c gstate. The passed array and offset
folow th esemantics of PostScipt's \c setdash command.
Return value:
\li 0 Success.
\li -1 The system is out of memory.
*/
int hpgs_gstate_setdash(hpgs_gstate *gstate,
const float *dash_lengths,
unsigned n_dashes, double offset)
{
if (gstate->dash_lengths) free(gstate->dash_lengths);
gstate->n_dashes = n_dashes;
gstate->dash_offset = offset;
if (gstate->n_dashes)
{
gstate->dash_lengths = (float *)malloc(sizeof(float)*gstate->n_dashes);
if (!gstate->dash_lengths)
{
gstate->n_dashes = 0;
return -1;
}
memmove(gstate->dash_lengths,dash_lengths,sizeof(float)*gstate->n_dashes);
}
else
gstate->dash_lengths = 0;
return 0;
}

View File

@ -0,0 +1,75 @@
/***********************************************************************
* *
* $Id: hpgsi18n.c 270 2006-01-29 21:12:23Z softadm $
* *
* hpgs - HPGl Script, a hpgl/2 interpreter, which uses a Postscript *
* API for rendering a scene and thus renders to a variety of *
* devices and fileformats. *
* *
* (C) 2004-2006 ev-i Informationstechnologie GmbH http://www.ev-i.at *
* *
* Author: Wolfgang Glas *
* *
* hpgs is free software; you can redistribute it and/or *
* modify it under the terms of the GNU Lesser General Public *
* License as published by the Free Software Foundation; either *
* version 2.1 of the License, or (at your option) any later version. *
* *
* hpgs is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU *
* Lesser General Public License for more details. *
* *
* You should have received a copy of the GNU Lesser General Public *
* License along with this library; if not, write to the *
* Free Software Foundation, Inc., 59 Temple Place, Suite 330, *
* Boston, MA 02111-1307 USA *
* *
***********************************************************************
* *
* Private subroutines used by subroutines of the library. *
* *
***********************************************************************/
#include <hpgsi18n.h>
#ifdef HPGS_HAVE_GETTEXT
#define HPGS_I18N_DOMAIN "hpgs"
void hpgs_i18n_init()
{
char *sp = hpgs_sprintf_malloc("%s%cshare%clocale",
hpgs_get_prefix(),
HPGS_PATH_SEPARATOR,
HPGS_PATH_SEPARATOR);
if (!sp) return;
bindtextdomain(HPGS_I18N_DOMAIN,sp);
free(sp);
}
const char *hpgs_i18n(const char *msg)
{
return dgettext(HPGS_I18N_DOMAIN,msg);
}
const char *hpgs_i18n_n(const char *msg,
const char *msg_plural,
unsigned long n)
{
return dngettext(HPGS_I18N_DOMAIN,msg,msg_plural,n);
}
#else
const char *hpgs_i18n(const char *msg)
{ return msg; }
const char *hpgs_i18n_n(const char *msg,
const char *msg_plural,
unsigned long n)
{ return n==1 ? msg : msg_plural; }
#endif // HPGS_HAVE_GETTEXT

View File

@ -0,0 +1,46 @@
/***********************************************************************
* *
* $Id: hpgsi18n.h 270 2006-01-29 21:12:23Z softadm $
* *
* hpgs - HPGl Script, a hpgl/2 interpreter, which uses a Postscript *
* API for rendering a scene and thus renders to a variety of *
* devices and fileformats. *
* *
* (C) 2004-2006 ev-i Informationstechnologie GmbH http://www.ev-i.at *
* *
* Author: Wolfgang Glas *
* *
* hpgs is free software; you can redistribute it and/or *
* modify it under the terms of the GNU Lesser General Public *
* License as published by the Free Software Foundation; either *
* version 2.1 of the License, or (at your option) any later version. *
* *
* hpgs is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU *
* Lesser General Public License for more details. *
* *
* You should have received a copy of the GNU Lesser General Public *
* License along with this library; if not, write to the *
* Free Software Foundation, Inc., 59 Temple Place, Suite 330, *
* Boston, MA 02111-1307 USA *
* *
***********************************************************************
* *
* Private subroutines used by i18n facilities of the library. *
* *
***********************************************************************/
#ifndef __HPGS_I18N_H__
#define __HPGS_I18N_H__
#include <hpgs.h>
#ifdef HPGS_HAVE_GETTEXT
#include <libintl.h>
HPGS_INTERNAL_API void hpgs_i18n_init();
#endif // HPGS_HAVE_GETTEXT
#endif // ! __HPGS_I18N_H__

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,77 @@
/***********************************************************************
* *
* $Id: hpgsimage.h 270 2006-01-29 21:12:23Z softadm $
* *
* hpgs - HPGl Script, a hpgl/2 interpreter, which uses a Postscript *
* API for rendering a scene and thus renders to a variety of *
* devices and fileformats. *
* *
* (C) 2004-2006 ev-i Informationstechnologie GmbH http://www.ev-i.at *
* *
* Author: Wolfgang Glas *
* *
* hpgs is free software; you can redistribute it and/or *
* modify it under the terms of the GNU Lesser General Public *
* License as published by the Free Software Foundation; either *
* version 2.1 of the License, or (at your option) any later version. *
* *
* hpgs is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU *
* Lesser General Public License for more details. *
* *
* You should have received a copy of the GNU Lesser General Public *
* License along with this library; if not, write to the *
* Free Software Foundation, Inc., 59 Temple Place, Suite 330, *
* Boston, MA 02111-1307 USA *
* *
***********************************************************************
* *
* Private declarations for images. *
* *
***********************************************************************/
#ifndef __HPGS_IMAGE_H__
#define __HPGS_IMAGE_H__
#include <hpgs.h>
#ifdef __cplusplus
extern "C" {
#endif
/*! \brief An concrete pixel image.
This structure has a public alias \c hpgs_png_image and
implements \c hpgs_image. The storage format is similar
to the format used by \c libpng, so the image may be written
to png file using \c hpgs_png_image_write.
*/
/*! @addtogroup image
* @{
*/
struct hpgs_png_image_st {
hpgs_image inherited;
int depth; //!< The bit depth of the image.
int color_type; //!< The color type.
int bytes_per_row; //!< The number of bytes per row of the pixel data.
int compression; //!< The compression used for writing the image in the range from 0 to 9.
unsigned char *data; //!< The pixel data.
hpgs_rop3_func_t rop3; //!< The ROP3 raster operation.
hpgs_palette_color pattern_color; //!< The color of the ROP3 pattern.
unsigned res_x; //!< The number of pixels per meter in x-direction, or 0 if unknown.
unsigned res_y; //!< The number of pixels per meter in y-direction, or 0 if unknown.
};
/*! @} */ /* end of group reader */
#ifdef __cplusplus
} // end of extern "C"
#endif
#endif // ! __HPGS_IMAGE_H__

View File

@ -0,0 +1,551 @@
/***********************************************************************
* *
* $Id: hpgsimagerop.c 372 2007-01-14 18:16:03Z softadm $
* *
* hpgs - HPGl Script, a hpgl/2 interpreter, which uses a Postscript *
* API for rendering a scene and thus renders to a variety of *
* devices and fileformats. *
* *
* (C) 2004-2006 ev-i Informationstechnologie GmbH http://www.ev-i.at *
* *
* Author: Wolfgang Glas *
* *
* hpgs is free software; you can redistribute it and/or *
* modify it under the terms of the GNU Lesser General Public *
* License as published by the Free Software Foundation; either *
* version 2.1 of the License, or (at your option) any later version. *
* *
* hpgs is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU *
* Lesser General Public License for more details. *
* *
* You should have received a copy of the GNU Lesser General Public *
* License along with this library; if not, write to the *
* Free Software Foundation, Inc., 59 Temple Place, Suite 330, *
* Boston, MA 02111-1307 USA *
* *
***********************************************************************
* *
* The implementation of the ROP3 clip frame extraction from images. *
* *
***********************************************************************/
#include <hpgs.h>
#include <assert.h>
#if defined ( __MINGW32__ ) || defined ( _MSC_VER )
#include<malloc.h>
#else
#include<alloca.h>
#endif
// #define HPGS_IMAGE_ROP_DEBUG
typedef struct hpgs_img_clip_seg_st hpgs_img_clip_seg;
struct hpgs_img_clip_seg_st
{
int j;
int i_vert;
};
typedef struct hpgs_img_clip_line_st hpgs_img_clip_line;
struct hpgs_img_clip_line_st
{
int i0;
int j0;
int i1;
int j1;
int key;
int usage;
};
#define MK_LINE_KEY(i,j) ((j)+(img->width+1)*(i))
static int compare_clip_lines (const void *a, const void *b)
{
const hpgs_img_clip_line *la = (const hpgs_img_clip_line *)a;
const hpgs_img_clip_line *lb = (const hpgs_img_clip_line *)b;
if (la->key < lb->key) return -1;
if (la->key > lb->key) return 1;
return 0;
}
static int grow_clip_lines (hpgs_device *device,
hpgs_img_clip_line **clip_lines,
size_t *clip_lines_sz)
{
size_t nsz = *clip_lines_sz*2;
hpgs_img_clip_line *ncl=realloc(*clip_lines,nsz*sizeof(hpgs_img_clip_line));
if (!ncl)
return hpgs_set_error(hpgs_i18n("hpgs_image_rop3_clip: Out of memory growing temporary storage."));
*clip_lines = ncl;
*clip_lines_sz = nsz;
return 0;
}
/*!
Sets a clip frame to the given device, which encloses all regions
of the device, which are cover by the image taking into account
the given ROP3 transfer function.
The argument \c data must contain a pointer to a two-dimensional
array of raw pixels of the size of the image. This array is filled
with pixel values as if the image has been painted to a white
destination area using the given ROP3 function.
Return values:
\li 0 The clip frame is empty, no operation has been performed on
the output device.
\li 1 The clip frame is not empty, the clip path has been
set to the output device using clipsave/moveto/lineto/clip
operations.
\li 2 The clip frame covers the whole image, no operation has been
performed on the output device.
\li 3 The clip frame is not empty, the visible pixels have all the same color
and clip path has been set to the output device using
moveto/lineto/setrgbcolor/fill operations. The image does not have to be
transferred by subsequent functions, the rgb color of the device has been
altered.
\li -1 An error occured on the output device.
*/
int hpgs_image_rop3_clip(hpgs_device *device,
hpgs_palette_color *data,
const hpgs_image *img,
const hpgs_point *ll, const hpgs_point *lr,
const hpgs_point *ur,
const hpgs_palette_color *p,
hpgs_xrop3_func_t xrop3)
{
// The upper bound for clip_lines_sz is (w+1)*(h+1)*2.
// This formula is chosen so, that for w==1 and h==1,
// this result is achieved. For larger pictures, we
// use 1/8th of the upper bound, which is pretty conservative.
// If not doing so, the algorithm easily consumes up to 1GB or more,
// which is too much for alloca, too. So this estimation combined
// with the usage of malloc should make the code robust.
size_t clip_lines_sz = ((img->width+1)*(img->height+1)+31)/4;
hpgs_img_clip_line *clip_lines = (hpgs_img_clip_line *)
malloc(sizeof(hpgs_img_clip_line)*clip_lines_sz);
hpgs_img_clip_seg *segs0 = (hpgs_img_clip_seg *)
hpgs_alloca(sizeof(hpgs_img_clip_seg)*(img->width+1));
hpgs_img_clip_seg *segs1 = (hpgs_img_clip_seg *)
hpgs_alloca(sizeof(hpgs_img_clip_seg)*(img->width+1));
if (!clip_lines || !segs0 || !segs1)
return hpgs_set_error(hpgs_i18n("hpgs_image_rop3_clip: Out of memory allocating temporary storage."));
int n_clip_lines = 0;
int ret = -1;
int i_seg0,n_segs0 = 0;
int i_seg1,n_segs1 = 0;
hpgs_point ul;
int i,j;
hpgs_bool all_visible = HPGS_TRUE;
hpgs_palette_color *first_visible_pixel = 0;
hpgs_bool single_color = HPGS_FALSE;
ul.x = ll->x + (ur->x - lr->x);
ul.y = ll->y + (ur->y - lr->y);
// first, accumulate lines.
for (i=0;i<img->height+1;++i)
{
// cut the current raster line
int t_last = 1;
n_segs1 = 0;
// this is here in order to construct all lines
// for the very last grid line
if (i<img->height)
{
for (j=0;j<img->width;++j)
{
int t;
hpgs_paint_color s;
unsigned r,g,b;
hpgs_image_get_pixel(img,j,i,&s,0);
r = xrop3(s.r,p->r);
g = xrop3(s.g,p->g);
b = xrop3(s.b,p->b);
// transparent ?
t = (r == 0x00ff && g == 0x00ff && b == 0x00ff);
if (t != t_last) // last pixel different transparency ?
{
segs1[n_segs1].j = j;
segs1[n_segs1].i_vert = -1;
++n_segs1;
}
t_last = t;
data->r = (unsigned char)r;
data->g = (unsigned char)g;
data->b = (unsigned char)b;
if (!t)
{
if (!first_visible_pixel)
{
first_visible_pixel = data;
single_color = HPGS_TRUE;
}
else if (single_color &&
(first_visible_pixel->r != data->r ||
first_visible_pixel->g != data->g ||
first_visible_pixel->b != data->b ))
single_color = HPGS_FALSE;
}
++data;
}
if (n_segs1 != 1 || segs1[0].j > 0)
all_visible = HPGS_FALSE;
// close trailing visible segment.
if (t_last == 0)
{
segs1[n_segs1].j = j;
segs1[n_segs1].i_vert = -1;
++n_segs1;
}
}
assert(n_segs1 <= (img->width+1));
#ifdef HPGS_IMAGE_ROP_DEBUG
hpgs_log("i=%d: segs1:",i);
for (j=0;j<n_segs1;++j)
hpgs_log("%c%d",j?',':' ',segs1[j].j);
hpgs_log("\n");
j=n_clip_lines;
#endif
// construct lines.
i_seg0 = 0;
i_seg1 = 0;
t_last = -1;
while (i_seg0 < n_segs0 || i_seg1 < n_segs1)
{
if (i_seg1 >= n_segs1 || (i_seg0 < n_segs0 && segs0[i_seg0].j < segs1[i_seg1].j))
{
// horizontal line.
if (t_last >= 0)
{
clip_lines[n_clip_lines].i0 = i;
clip_lines[n_clip_lines].i1 = i;
// check for the orientation.
if (i_seg0 & 1)
{
clip_lines[n_clip_lines].j0 = t_last;
clip_lines[n_clip_lines].j1 = segs0[i_seg0].j;
}
else
{
clip_lines[n_clip_lines].j0 = segs0[i_seg0].j;
clip_lines[n_clip_lines].j1 = t_last;
}
if (++n_clip_lines >= clip_lines_sz &&
grow_clip_lines(device,&clip_lines,&clip_lines_sz))
goto cleanup;
t_last = -1;
}
else
t_last = segs0[i_seg0].j;
++i_seg0;
}
else if (i_seg0 >= n_segs0 || segs1[i_seg1].j < segs0[i_seg0].j)
{
// horizontal line.
if (t_last >= 0)
{
clip_lines[n_clip_lines].i0 = i;
clip_lines[n_clip_lines].i1 = i;
// check for the orientation.
if (i_seg1 & 1)
{
clip_lines[n_clip_lines].j0 = segs1[i_seg1].j;
clip_lines[n_clip_lines].j1 = t_last;
}
else
{
clip_lines[n_clip_lines].j0 = t_last;
clip_lines[n_clip_lines].j1 = segs1[i_seg1].j;
}
if (++n_clip_lines >= clip_lines_sz &&
grow_clip_lines(device,&clip_lines,&clip_lines_sz))
goto cleanup;
t_last = -1;
}
else
t_last = segs1[i_seg1].j;
// create vertical line.
clip_lines[n_clip_lines].j0 = segs1[i_seg1].j;
clip_lines[n_clip_lines].j1 = segs1[i_seg1].j;
// check for the orientation.
if (i_seg1 & 1)
{
clip_lines[n_clip_lines].i0 = i+1;
clip_lines[n_clip_lines].i1 = i;
}
else
{
clip_lines[n_clip_lines].i0 = i;
clip_lines[n_clip_lines].i1 = i+1;
}
segs1[i_seg1].i_vert = n_clip_lines;
if (++n_clip_lines >= clip_lines_sz &&
grow_clip_lines(device,&clip_lines,&clip_lines_sz))
goto cleanup;
++i_seg1;
}
else
{
assert(segs0[i_seg0].j == segs1[i_seg1].j);
// horizontal line.
if (t_last >= 0)
{
clip_lines[n_clip_lines].i0 = i;
clip_lines[n_clip_lines].i1 = i;
// check for the orientation.
if (i_seg1 & 1)
{
clip_lines[n_clip_lines].j0 = segs1[i_seg1].j;
clip_lines[n_clip_lines].j1 = t_last;
}
else
{
clip_lines[n_clip_lines].j0 = t_last;
clip_lines[n_clip_lines].j1 = segs1[i_seg1].j;
}
if (++n_clip_lines >= clip_lines_sz &&
grow_clip_lines(device,&clip_lines,&clip_lines_sz))
goto cleanup;
}
if ((i_seg0 & 1) == (i_seg1 & 1))
{
// extend segment
int il = segs0[i_seg0].i_vert;
if (i_seg1 & 1)
clip_lines[il].i0 = i+1;
else
clip_lines[il].i1= i+1;
segs1[i_seg1].i_vert = il;
t_last = -1;
}
else
{
// create new segment.
clip_lines[n_clip_lines].j0 = segs1[i_seg1].j;
clip_lines[n_clip_lines].j1 = segs1[i_seg1].j;
if (i_seg1 & 1)
{
clip_lines[n_clip_lines].i0 = i+1;
clip_lines[n_clip_lines].i1 = i;
}
else
{
clip_lines[n_clip_lines].i0 = i;
clip_lines[n_clip_lines].i1 = i+1;
}
segs1[i_seg1].i_vert = n_clip_lines;
if (++n_clip_lines >= clip_lines_sz &&
grow_clip_lines(device,&clip_lines,&clip_lines_sz))
goto cleanup;
t_last = segs1[i_seg1].j;
}
++i_seg0;
++i_seg1;
}
}
#ifdef HPGS_IMAGE_ROP_DEBUG
hpgs_log("i=%d: lines: ",i);
for (;j<n_clip_lines;++j)
hpgs_log("(%d,%d,%d,%d)",
clip_lines[j].i0,clip_lines[j].j0,
clip_lines[j].i1,clip_lines[j].j1);
hpgs_log("\n");
#endif
assert (t_last == -1);
// swap clip segment caches
{
hpgs_img_clip_seg *tmp = segs0;
segs0=segs1;
segs1=tmp;
}
n_segs0 = n_segs1;
}
#ifdef HPGS_IMAGE_ROP_DEBUG
hpgs_log("clip_img: n_clip_lines,all_visible = %d,%d.\n",
n_clip_lines,all_visible);
#endif
if (n_clip_lines <= 0) { ret = 0; goto cleanup; }
if (all_visible && !single_color) { ret = 2; goto cleanup; }
assert(n_clip_lines <= (img->width+1)*(img->height+1)*2);
// OK, now create the lookup key of the lines.
for (i=0;i<n_clip_lines;++i)
{
clip_lines[i].key = MK_LINE_KEY(clip_lines[i].i0,clip_lines[i].j0);
clip_lines[i].usage = 0;
}
// sort the table
qsort(clip_lines,n_clip_lines,sizeof(hpgs_img_clip_line),compare_clip_lines);
if (!single_color && hpgs_clipsave(device)) goto cleanup;
// now construct the clip path.
for (i = 0;i<n_clip_lines;++i)
{
hpgs_img_clip_line *line = clip_lines+i;
int iline = 0;
if (line->usage) continue;
do
{
hpgs_point p;
int key,i0,i1;
p.x = ul.x +
line->j0 * (lr->x - ll->x) / img->width +
line->i0 * (lr->x - ur->x) / img->height ;
p.y = ul.y +
line->j0 * (lr->y - ll->y) / img->width +
line->i0 * (lr->y - ur->y) / img->height ;
key = MK_LINE_KEY(line->i1,line->j1);
if (iline)
{
if (hpgs_lineto(device,&p)) goto cleanup;
}
else
{
if (hpgs_moveto(device,&p)) goto cleanup;
}
#ifdef HPGS_IMAGE_ROP_DEBUG
hpgs_log("(%d,%d,%d,%d)",
line->i0,line->j0,
line->i1,line->j1);
#endif
++iline;
line->usage=1;
// binary search
i0 = 0;
i1 = n_clip_lines;
while (i1>i0)
{
int ii = i0+(i1-i0)/2;
if (clip_lines[ii].key < key)
i0 = ii+1;
else
i1 = ii;
}
while (clip_lines[i0].usage &&
i0 < n_clip_lines-1 &&
clip_lines[i0+1].key == key)
++i0;
assert(i0 < n_clip_lines && key == clip_lines[i0].key);
line = clip_lines+i0;
assert (line);
if (line->usage && line < clip_lines + n_clip_lines &&
line[1].key == key)
++line;
}
while (!line->usage);
assert (line->i0 == clip_lines[i].i0 &&
line->j0 == clip_lines[i].j0 );
#ifdef HPGS_IMAGE_ROP_DEBUG
hpgs_log("\n");
#endif
if (hpgs_closepath(device)) goto cleanup;
}
if (single_color)
{
hpgs_color c;
c.r = first_visible_pixel->r / 255.0;
c.g = first_visible_pixel->g / 255.0;
c.b = first_visible_pixel->b / 255.0;
if (hpgs_setrgbcolor(device,&c)) goto cleanup;
if (hpgs_fill(device,HPGS_FALSE)) goto cleanup;
if (hpgs_newpath(device)) goto cleanup;
ret = 3;
}
else
{
if (hpgs_clip(device,HPGS_FALSE)) goto cleanup;
if (hpgs_newpath(device)) goto cleanup;
ret = 1;
}
cleanup:
if (clip_lines) free(clip_lines);
return ret;
}

View File

@ -0,0 +1,278 @@
/***********************************************************************
* *
* $Id: hpgsistream.c 343 2006-08-18 16:48:09Z softadm $
* *
* hpgs - HPGl Script, a hpgl/2 interpreter, which uses a Postscript *
* API for rendering a scene and thus renders to a variety of *
* devices and fileformats. *
* *
* (C) 2004-2006 ev-i Informationstechnologie GmbH http://www.ev-i.at *
* *
* Author: Wolfgang Glas *
* *
* hpgs is free software; you can redistribute it and/or *
* modify it under the terms of the GNU Lesser General Public *
* License as published by the Free Software Foundation; either *
* version 2.1 of the License, or (at your option) any later version. *
* *
* hpgs is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU *
* Lesser General Public License for more details. *
* *
* You should have received a copy of the GNU Lesser General Public *
* License along with this library; if not, write to the *
* Free Software Foundation, Inc., 59 Temple Place, Suite 330, *
* Boston, MA 02111-1307 USA *
* *
***********************************************************************
* *
* The implementations of input streams. *
* *
***********************************************************************/
#include <hpgs.h>
#include <math.h>
#include <string.h>
#include <errno.h>
static int file_seek (FILE *file, size_t pos)
{
return fseek(file,pos,SEEK_SET);
}
static int file_seekend (FILE *file, size_t pos)
{
return fseek(file,-(long)pos,SEEK_END);
}
static int file_tell (FILE *file, size_t *pos)
{
long pp=ftell(file);
if (pp<0) return -1;
*pos = pp;
return 0;
}
/*! \defgroup base Basic facilities.
This module contains structures for operating on abstract input streams
as well as color structures and a 2D point.
*/
static hpgs_istream_vtable file_vtable =
{
(hpgs_istream_getc_func_t) getc,
(hpgs_istream_ungetc_func_t) ungetc,
(hpgs_istream_close_func_t) fclose,
(hpgs_istream_iseof_func_t) feof,
(hpgs_istream_iserror_func_t) ferror,
(hpgs_istream_seek_func_t) file_seek,
(hpgs_istream_tell_func_t) file_tell,
(hpgs_istream_read_func_t) fread,
(hpgs_istream_seekend_func_t) file_seekend
};
/*! Returns a new \c hpgs_istream created on the heap,
which operates on a file, which is opened by this call
in read-only mode.
Returns a null pointer, when an I/O error occurrs.
In this case, details about the the error can be retrieved
using \c errno.
*/
hpgs_istream *hpgs_new_file_istream(const char *fn)
{
FILE *in = fopen (fn,"rb");
hpgs_istream *ret = 0;
if (!in) return 0;
ret = (hpgs_istream *)malloc(sizeof(hpgs_istream));
if (!ret)
{
fclose(in);
return 0;
}
ret->stream = in;
ret->vtable = &file_vtable;
return ret;
}
/* memory stream implementation functions. */
typedef struct hpgs_mem_istream_stream_st hpgs_mem_istream_stream;
struct hpgs_mem_istream_stream_st
{
const unsigned char *data;
const unsigned char *gptr;
const unsigned char *eptr;
int errflg;
};
static int mem_getc (hpgs_mem_istream_stream *stream)
{
int ret;
if (stream->errflg)
ret=EOF;
else
{
if (stream->gptr >= stream->eptr)
ret = EOF;
else
{
ret = *stream->gptr;
++stream->gptr;
}
}
return ret;
}
static int mem_ungetc (int c, hpgs_mem_istream_stream *stream)
{
if (stream->errflg) return -1;
if (stream->gptr <= stream->data) { stream->errflg = 1; return -1; }
--stream->gptr;
return 0;
}
static int mem_close (hpgs_mem_istream_stream *stream)
{
return 0;
}
static int mem_iseof (hpgs_mem_istream_stream *stream)
{
return stream->gptr >= stream->eptr;
}
static int mem_iserror (hpgs_mem_istream_stream *stream)
{
return stream->errflg;
}
static int mem_tell (hpgs_mem_istream_stream *stream, size_t *pos)
{
if (stream->errflg) return -1;
*pos = stream->gptr - stream->data;
return 0;
}
static int mem_seek (hpgs_mem_istream_stream *stream, size_t pos)
{
if (stream->data + pos > stream->eptr)
{
stream->errflg = 1;
return -1;
}
stream->gptr = stream->data+pos;
stream->errflg = 0;
return 0;
}
static int mem_seekend (hpgs_mem_istream_stream *stream, size_t pos)
{
if (stream->data + pos > stream->eptr)
{
stream->errflg = 1;
return -1;
}
stream->gptr = stream->eptr-pos;
stream->errflg = 0;
return 0;
}
static size_t mem_read (void *ptr, size_t size, size_t nmemb, hpgs_mem_istream_stream *stream)
{
size_t ret = 0;
if (!stream->errflg)
{
if (stream->gptr < stream->eptr)
{
ret = (stream->eptr - stream->gptr)/size;
if (ret > nmemb) ret = nmemb;
memcpy(ptr,stream->gptr,size * ret);
stream->gptr += size * ret;
}
}
return ret;
}
static hpgs_istream_vtable mem_vtable =
{
(hpgs_istream_getc_func_t) mem_getc,
(hpgs_istream_ungetc_func_t) mem_ungetc,
(hpgs_istream_close_func_t) mem_close,
(hpgs_istream_iseof_func_t) mem_iseof,
(hpgs_istream_iserror_func_t) mem_iserror,
(hpgs_istream_seek_func_t) mem_seek,
(hpgs_istream_tell_func_t) mem_tell,
(hpgs_istream_read_func_t) mem_read,
(hpgs_istream_seekend_func_t) mem_seekend
};
/*! Returns a new \c hpgs_istream created on the heap,
which operates on a chunk of memory in the given
location with the given size.
Returns a null pointer, when the system is out of memory.
*/
hpgs_istream *hpgs_new_mem_istream(const unsigned char *data,
size_t data_size,
hpgs_bool dup)
{
#define HPGS_ISTREAM_PAD_SZ (8*((sizeof(hpgs_istream)+7)/8))
#define HPGS_ISTREAM_STREAM_PAD_SZ (8*((sizeof(hpgs_mem_istream_stream)+7)/8))
hpgs_mem_istream_stream *stream;
hpgs_istream *ret;
size_t sz = HPGS_ISTREAM_PAD_SZ + HPGS_ISTREAM_STREAM_PAD_SZ;
void *ptr;
if (dup) sz += data_size;
ptr = malloc(sz);
ret = (hpgs_istream *)ptr;
if (!ret)
return 0;
stream = (hpgs_mem_istream_stream *)(ptr+HPGS_ISTREAM_PAD_SZ);
if (dup)
{
unsigned char *ddata =
(unsigned char *)ptr + HPGS_ISTREAM_PAD_SZ + HPGS_ISTREAM_STREAM_PAD_SZ;
stream->data = ddata;
stream->gptr = ddata;
stream->eptr = ddata+data_size;
memcpy(ddata,data,data_size);
}
else
{
stream->data = data;
stream->gptr = data;
stream->eptr = data+data_size;
}
stream->errflg = 0;
ret->stream = stream;
ret->vtable = &mem_vtable;
return ret;
}

View File

@ -0,0 +1,263 @@
/***********************************************************************
* *
* $Id: hpgslabel.c 381 2007-02-20 09:06:38Z softadm $
* *
* hpgs - HPGl Script, a hpgl/2 interpreter, which uses a Postscript *
* API for rendering a scene and thus renders to a variety of *
* devices and fileformats. *
* *
* (C) 2004-2006 ev-i Informationstechnologie GmbH http://www.ev-i.at *
* *
* Author: Wolfgang Glas *
* *
* hpgs is free software; you can redistribute it and/or *
* modify it under the terms of the GNU Lesser General Public *
* License as published by the Free Software Foundation; either *
* version 2.1 of the License, or (at your option) any later version. *
* *
* hpgs is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU *
* Lesser General Public License for more details. *
* *
* You should have received a copy of the GNU Lesser General Public *
* License along with this library; if not, write to the *
* Free Software Foundation, Inc., 59 Temple Place, Suite 330, *
* Boston, MA 02111-1307 USA *
* *
***********************************************************************
* *
* The implementation of old-style HPGL labels. *
* *
***********************************************************************/
#include <hpgsreader.h>
#include <string.h>
#include <errno.h>
#include <iconv.h>
#if defined ( __MINGW32__ ) || defined ( _MSC_VER )
#include<malloc.h>
#else
#include<alloca.h>
#endif
#define HPGS_LABEL_NFACES 4
#define HPGS_LABEL_NENC 27
typedef struct hpgs_ttf_face_info_st hpgs_ttf_face_info;
struct hpgs_ttf_face_info_st
{
const char *font_name;
double x_fac;
double y_fac;
};
#ifdef WIN32
#define HPGS_LABEL_UCS_TYPE unsigned
#define HPGS_LABEL_UCS_ENC "UCS-4-INTERNAL"
#else
#define HPGS_LABEL_UCS_TYPE wchar_t
#define HPGS_LABEL_UCS_ENC "WCHAR_T"
#endif
static hpgs_ttf_face_info face_infos[HPGS_LABEL_NFACES] =
{
{ "LetterGothic", 1.48, 1.295 },
{ "LetterGothic Italic", 1.48, 1.295 },
{ "LetterGothic Bold", 1.48, 1.295 },
{ "LetterGothic Bold Italic", 1.48, 1.295 }
};
static const char *encoding_names[HPGS_LABEL_NENC] =
{
"HP-ROMAN8",
"LATIN1", // 14
"LATIN2", // 78
"LATIN5", // 174
"GREEK8", // 263
"CSISO25FRENCH", // 6
"CSISO69FRENCH", // 38
"CSISO14JISC6220RO", // 11
"CSISO11SWEDISHFORNAMES", // 19
"CSISO10SWEDISH", // 115
"CSISO60NORWEGIAN1", // 4
"CSISO61NORWEGIAN2", // 36
"CSISO21GERMAN", // 39
"CSISO15ITALIAN", // 9
"CSISO17SPANISH", // 83
"CSISO85SPANISH2", // 211
"CSISO16PORTUGESE", // 147
"CSISO84PORTUGESE2", // 179
"HEBREW", // 8,264
"CYRILLIC", // 18, 50
"ECMA-CYRILLIC", // 334
"MS-MAC-CYRILLIC", // 114
"WINDOWS-1252", // 309
"CP850", // 405
"CP852", // 565
"ARABIC7", // 22
"ARABIC" // 278
};
static int hpgs_device_label_internal(hpgs_device *dev,
hpgs_point *pos,
const char *str, int str_len,
int face,
iconv_t encoding,
const char* encoding_name,
int posture,
int weight,
const hpgs_point *left_vec,
const hpgs_point *up_vec,
const hpgs_point *space_vec)
{
int iface = 0;
size_t i,len,inbytesleft;
HPGS_LABEL_UCS_TYPE ucs_str[HPGS_MAX_LABEL_SIZE];
size_t outbytesleft;
char *inbuf;
char *outbuf;
// get the face index.
if (posture)
iface += 1;
if (weight >= 3)
iface += 2;
// open the face.
hpgs_font *font = hpgs_find_font(face_infos[iface].font_name);
if (!font) return -1;
// convert to UNICODE
if (str_len > HPGS_MAX_LABEL_SIZE) str_len=HPGS_MAX_LABEL_SIZE;
inbytesleft = str_len;
outbytesleft = str_len*sizeof(HPGS_LABEL_UCS_TYPE);
inbuf = hpgs_alloca(str_len);
if (!inbuf)
return hpgs_set_error(hpgs_i18n("unable to allocate %d bytes of temporary string data."),
str_len);
memcpy(inbuf,str,str_len);
outbuf = (char*)ucs_str;
len=
iconv(encoding,&inbuf,&inbytesleft,&outbuf,&outbytesleft);
if (len == (size_t)(-1))
return hpgs_set_error(hpgs_i18n("unable to convert string to encoding %s: %s."),
encoding_name,strerror(errno));
len = (str_len*sizeof(HPGS_LABEL_UCS_TYPE) - outbytesleft) / sizeof(HPGS_LABEL_UCS_TYPE);
// OK, now let's go.
hpgs_matrix m;
m.mxx = left_vec->x * face_infos[iface].x_fac;
m.mxy = up_vec->x * face_infos[iface].y_fac;
m.myx = left_vec->y * face_infos[iface].x_fac;
m.myy = up_vec->y * face_infos[iface].y_fac;
for (i=0;i<len;i++)
{
m.dx = pos->x;
m.dy = pos->y;
unsigned gid = hpgs_font_get_glyph_id(font,(int)ucs_str[i]);
if (hpgs_font_draw_glyph(font,dev,&m,gid))
return -1;
pos->x += space_vec->x;
pos->y += space_vec->y;
}
return 0;
}
int hpgs_reader_label(hpgs_reader *reader,
const char *str, int str_len,
int face,
int encoding,
int posture,
int weight,
const hpgs_point *left_vec,
const hpgs_point *up_vec,
const hpgs_point *space_vec)
{
int ienc;
// open the encoding.
switch (encoding)
{
case 14: ienc = 1; break;
case 78: ienc = 2; break;
case 174: ienc = 3; break;
case 263: ienc = 4; break;
case 6: ienc = 5; break;
case 38: ienc = 6; break;
case 11: ienc = 7; break;
case 19: ienc = 8; break;
case 115: ienc = 9; break;
case 4: ienc = 10; break;
case 36: ienc = 11; break;
case 39: ienc = 12; break;
case 9: ienc = 13; break;
case 83: ienc = 14; break;
case 211: ienc = 15; break;
case 147: ienc = 16; break;
case 179: ienc = 17; break;
case 8: case 264: ienc = 18; break;
case 18: case 50: ienc = 19; break;
case 334: ienc = 20; break;
case 114: ienc = 21; break;
case 309: ienc = 22; break;
case 405: ienc = 23; break;
case 565: ienc = 24; break;
case 22: ienc = 25; break;
case 278: ienc = 26; break;
default: ienc = 0;
}
iconv_t ic = iconv_open(HPGS_LABEL_UCS_ENC,encoding_names[ienc]);
if (ic == (iconv_t)(-1))
return hpgs_set_error(hpgs_i18n("unable to open encoding %s."),
encoding_names[ienc]);
int ret =hpgs_device_label_internal(reader->device,&reader->current_point,
str,str_len,face,
ic,encoding_names[ienc],
posture,weight,left_vec,up_vec,space_vec);
iconv_close(ic);
return ret;
}
int hpgs_device_label(hpgs_device *dev,
hpgs_point *pos,
const char *str, int str_len,
int face,
const char *encoding,
int posture,
int weight,
const hpgs_point *left_vec,
const hpgs_point *up_vec,
const hpgs_point *space_vec)
{
// open the encoding.
iconv_t ic = iconv_open(HPGS_LABEL_UCS_ENC,encoding);
int ret;
if (ic == (iconv_t)(-1))
return hpgs_set_error(hpgs_i18n("unable to open encoding %s."),encoding);
ret = hpgs_device_label_internal(dev,pos,str,str_len,face,
ic,encoding,
posture,weight,left_vec,up_vec,space_vec);
iconv_close(ic);
return ret;
}

View File

@ -0,0 +1,353 @@
/***********************************************************************
* *
* $Id: hpgslexer.c 298 2006-03-05 18:18:03Z softadm $
* *
* hpgs - HPGl Script, a hpgl/2 interpreter, which uses a Postscript *
* API for rendering a scene and thus renders to a variety of *
* devices and fileformats. *
* *
* (C) 2004-2006 ev-i Informationstechnologie GmbH http://www.ev-i.at *
* *
* Author: Wolfgang Glas *
* *
* hpgs is free software; you can redistribute it and/or *
* modify it under the terms of the GNU Lesser General Public *
* License as published by the Free Software Foundation; either *
* version 2.1 of the License, or (at your option) any later version. *
* *
* hpgs is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU *
* Lesser General Public License for more details. *
* *
* You should have received a copy of the GNU Lesser General Public *
* License along with this library; if not, write to the *
* Free Software Foundation, Inc., 59 Temple Place, Suite 330, *
* Boston, MA 02111-1307 USA *
* *
***********************************************************************
* *
* The implementation of the HPGL reader. *
* *
***********************************************************************/
#include <hpgsreader.h>
#include <string.h>
#include <ctype.h>
int hpgs_reader_check_param_end(hpgs_reader *reader)
{
do
{
reader->last_byte = hpgs_getc(reader->in);
if (reader->last_byte == EOF)
return -1;
}
while (isspace(reader->last_byte));
reader->bytes_ignored = 0;
if (reader->last_byte == ';')
{
reader->bytes_ignored = 0;
reader->eoc = 1;
return 0;
}
if (reader->last_byte == ',')
{
do
{
reader->last_byte = hpgs_getc(reader->in);
if (reader->last_byte == EOF)
return -1;
}
while (isspace(reader->last_byte));
if (isalpha(reader->last_byte) || reader->last_byte == HPGS_ESC)
{
reader->bytes_ignored = 1;
reader->eoc = 1;
return 0;
}
else
{
hpgs_ungetc(reader->last_byte,reader->in);
reader->bytes_ignored = 0;
reader->eoc = 0;
return 0;
}
}
if (reader->last_byte == '"' || reader->last_byte == '\'' ||
isdigit(reader->last_byte) ||
reader->last_byte == '+' || reader->last_byte == '-' ||
reader->last_byte == '.')
{
hpgs_ungetc(reader->last_byte,reader->in);
reader->bytes_ignored = 0;
reader->eoc = 0;
return 0;
}
if (isalpha(reader->last_byte) || reader->last_byte == HPGS_ESC)
{
reader->bytes_ignored = 1;
reader->eoc = 1;
return 0;
}
return -1;
}
/* read an integer argument from the stream - PCL version
return values: -1... read error/EOF
0... no integer found.
1... integer found.
*/
int hpgs_reader_read_pcl_int(hpgs_reader *reader, int *x, int *sign)
{
*sign = 0;
*x=0;
reader->last_byte = hpgs_getc(reader->in);
if (reader->last_byte == EOF)
return -1;
if (reader->last_byte == '-')
{ *sign = -1; reader->last_byte=hpgs_getc(reader->in); }
else if (reader->last_byte == '+')
{ *sign = 1; reader->last_byte=hpgs_getc(reader->in); }
if (reader->last_byte == EOF)
return -1;
if (!isdigit(reader->last_byte))
{ hpgs_ungetc(reader->last_byte,reader->in); return 0; }
do
{
*x = 10 * (*x) + (reader->last_byte-'0');
reader->last_byte = hpgs_getc(reader->in);
if (reader->last_byte == EOF)
return -1;
}
while (isdigit(reader->last_byte));
hpgs_ungetc(reader->last_byte,reader->in);
if (*sign < 0)
*x = -*x;
return 1;
}
/* read an integer argument from the stream
return values: -1... read error/EOF
0... success.
1... End of command.
*/
int hpgs_reader_read_int(hpgs_reader *reader, int *x)
{
int sign = 0;
if (reader->eoc) return -1;
*x=0;
do
{
reader->last_byte = hpgs_getc(reader->in);
if (reader->last_byte == EOF)
return -1;
}
while (isspace(reader->last_byte) || reader->last_byte==',');
if (reader->last_byte == '-')
sign = 1;
else if (reader->last_byte == '+')
sign = 0;
else if (isdigit(reader->last_byte))
hpgs_ungetc(reader->last_byte,reader->in);
else
return -1;
while (1)
{
reader->last_byte = hpgs_getc(reader->in);
if (reader->last_byte == EOF)
return -1;
if (isdigit(reader->last_byte))
*x = 10 * (*x) + (reader->last_byte-'0');
else
break;
}
hpgs_ungetc(reader->last_byte,reader->in);
return hpgs_reader_check_param_end(reader);
}
/* read a double argument from the stream
return values: -1... read error/EOF
0... success.
1... End of command.
*/
int hpgs_reader_read_double(hpgs_reader *reader, double *x)
{
int sign = 0;
if (reader->eoc) return -1;
*x=0.0;
do
{
reader->last_byte = hpgs_getc(reader->in);
if (reader->last_byte == EOF)
return -1;
}
while (isspace(reader->last_byte) || reader->last_byte==',');
if (reader->last_byte == '-')
sign = 1;
else if (reader->last_byte == '+')
sign = 0;
else if (!isdigit(reader->last_byte) && reader->last_byte != '.')
return -1;
if (isdigit(reader->last_byte))
hpgs_ungetc(reader->last_byte,reader->in);
if (reader->last_byte != '.')
while (1)
{
reader->last_byte = hpgs_getc(reader->in);
if (reader->last_byte == EOF)
return -1;
if (isdigit(reader->last_byte))
*x = 10.0 * (*x) + (reader->last_byte-'0');
else
break;
}
if (reader->last_byte == '.')
{
double xx=1.0;
while (1)
{
reader->last_byte = hpgs_getc(reader->in);
if (reader->last_byte == EOF)
return -1;
xx *= 0.1;
if (isdigit(reader->last_byte))
*x += xx * (reader->last_byte-'0');
else
break;
}
}
hpgs_ungetc(reader->last_byte,reader->in);
if (sign) *x = -*x;
return hpgs_reader_check_param_end(reader);
}
int hpgs_reader_read_point(hpgs_reader *reader, hpgs_point *p, int xform)
{
if (hpgs_reader_read_double(reader,&p->x)) return -1;
if (reader->eoc) return -1;
if (hpgs_reader_read_double(reader,&p->y)) return -1;
switch (xform)
{
case 1:
hpgs_matrix_xform (p,&reader->total_matrix,p);
break;
case -1:
hpgs_matrix_scale (p,&reader->total_matrix,p);
break;
default:
break;
}
return 0;
}
/* read an integer argument from the stream
return values: -1... read error/EOF
0... success.
1... End of command.
*/
int hpgs_reader_read_new_string(hpgs_reader *reader, char *str)
{
int term=',';
int i=0;
if (reader->eoc) return -1;
do
{
reader->last_byte = hpgs_getc(reader->in);
if (reader->last_byte == EOF)
return -1;
}
while (isspace(reader->last_byte));
if (reader->last_byte == '\'' || reader->last_byte=='"')
term = reader->last_byte;
else
str[i++] = reader->last_byte;
do
{
reader->last_byte = hpgs_getc(reader->in);
if (reader->last_byte == EOF)
return -1;
if (i<HPGS_MAX_LABEL_SIZE)
str[i] = reader->last_byte;
++i;
if (term == ',' && reader->last_byte == ';') break;
}
while (reader->last_byte != term);
if (i) --i;
str[i] = '\0';
return hpgs_reader_check_param_end(reader);
}
int hpgs_reader_read_label_string(hpgs_reader *reader, char *str)
{
int i=0;
if (reader->eoc) return -1;
reader->bytes_ignored = 0;
do
{
reader->last_byte = hpgs_getc(reader->in);
if (reader->last_byte == EOF)
return -1;
if (i<HPGS_MAX_LABEL_SIZE)
str[i] = reader->last_byte;
++i;
}
while (reader->last_byte != reader->label_term);
if (reader->label_term_ignore && i)
--i;
str[i] = '\0';
return hpgs_reader_check_param_end(reader);
}

View File

@ -0,0 +1,223 @@
/***********************************************************************
* *
* $Id: hpgsmatrix.c 298 2006-03-05 18:18:03Z softadm $
* *
* hpgs - HPGl Script, a hpgl/2 interpreter, which uses a Postscript *
* API for rendering a scene and thus renders to a variety of *
* devices and fileformats. *
* *
* (C) 2004-2006 ev-i Informationstechnologie GmbH http://www.ev-i.at *
* *
* Author: Wolfgang Glas *
* *
* hpgs is free software; you can redistribute it and/or *
* modify it under the terms of the GNU Lesser General Public *
* License as published by the Free Software Foundation; either *
* version 2.1 of the License, or (at your option) any later version. *
* *
* hpgs is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU *
* Lesser General Public License for more details. *
* *
* You should have received a copy of the GNU Lesser General Public *
* License along with this library; if not, write to the *
* Free Software Foundation, Inc., 59 Temple Place, Suite 330, *
* Boston, MA 02111-1307 USA *
* *
***********************************************************************
* *
* The implementation of the public API for transformation matrices. *
* *
***********************************************************************/
#include<hpgs.h>
/*!
Sets the given matrix to the identity matrix.
*/
void hpgs_matrix_set_identity(hpgs_matrix *m)
{
m->myx = m->mxy = m->dy = m->dx = 0.0;
m->myy = m->mxx = 1.0;
}
/*!
Transforms the given point \c p with the matrix \c m.
The result is stored in \c res.
The pointers \c p and \c res may point to the same memory location.
*/
void hpgs_matrix_xform(hpgs_point *res,
const hpgs_matrix *m, const hpgs_point *p)
{
double x = m->dx + m->mxx * p->x + m->mxy * p->y;
double y = m->dy + m->myx * p->x + m->myy * p->y;
res->x = x;
res->y = y;
}
/*!
Transforms the given point \c p with the inverse of the matrix \c m.
The result is stored in \c res.
The pointers \c p and \c res may point to the same memory location.
*/
void hpgs_matrix_ixform(hpgs_point *res,
const hpgs_point *p, const hpgs_matrix *m)
{
double x0 = (p->x - m->dx);
double y0 = (p->y - m->dy);
double det = m->mxx * m->myy - m->mxy * m->myx;
res->x = (m->myy * x0 - m->mxy * y0)/det;
res->y = (m->mxx * y0 - m->myx * x0)/det;
}
/*!
Transforms the given bounding box \c bb with the matrix \c m.
The result is the enclosing bounding box of the transformed
rectangle of the bounding box and is stored in \c res.
The pointers \c bb and \c res may point to the same memory location.
*/
void hpgs_matrix_xform_bbox(hpgs_bbox *res,
const hpgs_matrix *m, const hpgs_bbox *bb)
{
hpgs_point ll = { bb->llx, bb->lly };
hpgs_point ur = { bb->urx, bb->ury };
hpgs_point lr = { bb->llx, bb->ury };
hpgs_point ul = { bb->urx, bb->lly };
hpgs_matrix_xform(&ll,m,&ll);
hpgs_matrix_xform(&ur,m,&ur);
hpgs_matrix_xform(&lr,m,&lr);
hpgs_matrix_xform(&ul,m,&ul);
res->llx = HPGS_MIN(HPGS_MIN(ll.x,ur.x),HPGS_MIN(lr.x,ul.x));
res->lly = HPGS_MIN(HPGS_MIN(ll.y,ur.y),HPGS_MIN(lr.y,ul.y));
res->urx = HPGS_MAX(HPGS_MAX(ll.x,ur.x),HPGS_MAX(lr.x,ul.x));
res->ury = HPGS_MAX(HPGS_MAX(ll.y,ur.y),HPGS_MAX(lr.y,ul.y));
}
/*!
Transforms the given bounding box \c bb with the the inverse of
the matrix \c m.
The result is the enclosing bounding box of the transformed
rectangle of the bounding box and is stored in \c res.
The pointers \c bb and \c res may point to the same memory location.
*/
void hpgs_matrix_ixform_bbox(hpgs_bbox *res,
const hpgs_bbox *bb, const hpgs_matrix *m)
{
hpgs_point ll = { bb->llx, bb->lly };
hpgs_point ur = { bb->urx, bb->ury };
hpgs_point lr = { bb->llx, bb->ury };
hpgs_point ul = { bb->urx, bb->lly };
hpgs_matrix_ixform(&ll,&ll,m);
hpgs_matrix_ixform(&ur,&ur,m);
hpgs_matrix_ixform(&lr,&lr,m);
hpgs_matrix_ixform(&ul,&ul,m);
res->llx = HPGS_MIN(HPGS_MIN(ll.x,ur.x),HPGS_MIN(lr.x,ul.x));
res->lly = HPGS_MIN(HPGS_MIN(ll.y,ur.y),HPGS_MIN(lr.y,ul.y));
res->urx = HPGS_MAX(HPGS_MAX(ll.x,ur.x),HPGS_MAX(lr.x,ul.x));
res->ury = HPGS_MAX(HPGS_MAX(ll.y,ur.y),HPGS_MAX(lr.y,ul.y));
}
/*!
Transforms the given point \c p with the matrix \c m without
applying the translation part of \c m. This is useful in order
to transform delta vectors.
The result is stored in \c res.
The pointers \c p and \c res may point to the same memory location.
*/
void hpgs_matrix_scale(hpgs_point *res,
const hpgs_matrix *m, const hpgs_point *p)
{
double x = m->mxx * p->x + m->mxy * p->y;
double y = m->myx * p->x + m->myy * p->y;
res->x = x;
res->y = y;
}
/*!
Transforms the given point \c p with the inverse of the matrix \c m
without applying the translation part of \c m. This is useful in order
to transform delta vectors.
The result is stored in \c res.
The pointers \c p and \c res may point to the same memory location.
*/
void hpgs_matrix_iscale(hpgs_point *res,
const hpgs_point *p, const hpgs_matrix *m)
{
double x0 = p->x;
double y0 = p->y;
double det = m->mxx * m->myy - m->mxy * m->myx;
res->x = (m->myy * x0 - m->mxy * y0)/det;
res->y = (m->mxx * y0 - m->myx * x0)/det;
}
/*!
Concatenates the given matrices \c a and \c b.
The result is stored in \c res.
Either of the pointer \c a or \b may point to the same memory location as
the pointer \c res.
*/
void hpgs_matrix_concat(hpgs_matrix *res,
const hpgs_matrix *a, const hpgs_matrix *b)
{
//
// | 1 0 0 | | 1 0 0 | | 1 0 0 |
// | dx mxx mxy | x | Dx Mxx Mxy | = | dx+Dx*mxx+Dy*mxy mxx*Mxx+mxy*Myx mxx*Mxy+mxy*Myy |
// | dy myx myy | | Dy Myx Myy | | dy+Dx*myx+Dy*myy myx*Mxx+myy*Myx myx*Mxy+myy*Myy |
//
double r0,r1,r2,r3;
r0 = a->dx+b->dx*a->mxx+b->dy*a->mxy;
r1 = a->dy+b->dx*a->myx+b->dy*a->myy;
res->dx = r0;
res->dy = r1;
r0 = a->mxx*b->mxx+a->mxy*b->myx;
r1 = a->mxx*b->mxy+a->mxy*b->myy;
r2 = a->myx*b->mxx+a->myy*b->myx;
r3 = a->myx*b->mxy+a->myy*b->myy;
res->mxx = r0;
res->mxy = r1;
res->myx = r2;
res->myy = r3;
}
/*!
Inverts the given matrix \c m.
The result is stored in \c res.
The pointers \c m and \c res may point to the same memory location.
*/
void hpgs_matrix_invert(hpgs_matrix *res, const hpgs_matrix *m)
{
double det = m->mxx * m->myy - m->mxy * m->myx;
double tmp = m->mxx/det;
res->mxx = m->myy/det;
res->myy = tmp;
res->mxy = -m->mxy/det;
res->myx = -m->myx/det;
double x0 = -m->dx;
double y0 = -m->dy;
res->dx = x0 * res->mxx + y0 * res->mxy;
res->dy = x0 * res->myx + y0 * res->myy;
}

View File

@ -0,0 +1,527 @@
/***********************************************************************
* *
* $Id: hpgsmkrop.c 270 2006-01-29 21:12:23Z softadm $
* *
* hpgs - HPGl Script, a hpgl/2 interpreter, which uses a Postscript *
* API for rendering a scene and thus renders to a variety of *
* devices and fileformats. *
* *
* (C) 2004-2006 ev-i Informationstechnologie GmbH http://www.ev-i.at *
* *
* Author: Wolfgang Glas *
* *
* hpgs is free software; you can redistribute it and/or *
* modify it under the terms of the GNU Lesser General Public *
* License as published by the Free Software Foundation; either *
* version 2.1 of the License, or (at your option) any later version. *
* *
* hpgs is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU *
* Lesser General Public License for more details. *
* *
* You should have received a copy of the GNU Lesser General Public *
* License along with this library; if not, write to the *
* Free Software Foundation, Inc., 59 Temple Place, Suite 330, *
* Boston, MA 02111-1307 USA *
* *
***********************************************************************
* *
* A small programm, which generates the raster operations hpgsrop.c *
* *
***********************************************************************/
#include <stdio.h>
#include <stdarg.h>
#include <string.h>
#include <time.h>
#include <errno.h>
#ifdef __GNUC__
__attribute__((format(printf,4,5)))
#endif
static int apprintf (char *str, size_t str_sz, size_t *str_len,
const char *fmt, ...)
{
int n;
va_list ap;
va_start(ap, fmt);
n = vsnprintf(str+*str_len,str_sz-*str_len,fmt,ap);
va_end(ap);
if (n<0) { perror("snprintf"); return -1; }
*str_len+=n;
return 0;
}
static void mk_operand (char *operand, size_t operand_sz, const char *stack, int i)
{
switch (stack[i])
{
case 'D':
strcpy(operand,"*D");
break;
case 'S':
case 'T':
operand[0] = stack[i];
operand[1] = '\0';
break;
default:
snprintf(operand,operand_sz,"stk%d",i+1);
}
}
static void mk_xoperand (char *operand, size_t operand_sz, const char *stack, int i)
{
switch (stack[i])
{
case 'D':
strcpy(operand,"D");
break;
case 'S':
case 'T':
operand[0] = stack[i];
operand[1] = '\0';
break;
default:
snprintf(operand,operand_sz,"stk%d",i+1);
}
}
/*
This function converts a ROP3 description cf. to
PCL 5 Comparison Guide, Edition 2, 6/2003, Hewlett Packard
(May be downloaded as bpl13206.pdf from http://www.hp.com)
into 4 C-programs for all transparency modes supported by
HPGL/2 and PCL.
Additional information may be found under
http://msdn.microsoft.com/library/default.asp?url=/library/en-us/wceshellui5/html/wce50grfTernaryRasterOperations.asp
(especially typos in HP's documentation are corrected from
this source of information).
*/
static int write_rop3_func(FILE *out, int irop, const char *ropstr)
{
int stacksz = 0;
int max_stacksz = 0;
char stack[32];
char operand[32];
char operand2[32];
const char *c;
int D_used = 0;
int S_used = 0;
int T_used = 0;
char defn[2048],op;
size_t defn_len=0;
char xdefn[2048];
size_t xdefn_len=0;
int i;
defn[0] = '\0';
xdefn[0] = '\0';
for (c=ropstr;*c;++c)
switch (*c)
{
case '0':
case '1':
i = (*c == '0') ? 0 : 255;
max_stacksz = stacksz = 1;
if (c!=ropstr || *(c+1))
{
fprintf (stderr,"Misplaced %c in rop string %s.\n",
*c,ropstr);
return -1;
}
if (apprintf(defn,sizeof(defn),&defn_len,
" stk1 = %d;\n",i ))
return -1;
if (apprintf(xdefn,sizeof(xdefn),&xdefn_len,
" stk1 = %s;\n", (*c == '0') ? "0x0000" : "0xffff"))
return -1;
break;
case 'S':
case 'T':
case 'D':
if (stacksz >= sizeof(stack)-1)
{
fprintf (stderr,"Stack overflow in rop string %s.\n",ropstr);
return -1;
}
stack[stacksz] = *c;
++stacksz;
if (*c == 'D')
D_used = 1;
if (*c == 'T')
T_used = 1;
if (*c == 'S')
S_used = 1;
break;
case 'o':
case 'a':
case 'x':
if (stacksz<1)
{
fprintf (stderr,"Stack underflow in rop string %s.\n",ropstr);
return -1;
}
mk_operand(operand,sizeof(operand),stack,stacksz-2);
mk_operand(operand2,sizeof(operand),stack,stacksz-1);
op = (*c == 'o') ? '|' : ((*c == 'a') ? '&' : '^');
if (apprintf(defn,sizeof(defn),&defn_len,
" stk%d = %s %c %s;\n",
stacksz-1,operand,op,operand2 ))
return -1;
mk_xoperand(operand,sizeof(operand),stack,stacksz-2);
mk_xoperand(operand2,sizeof(operand),stack,stacksz-1);
if (apprintf(xdefn,sizeof(xdefn),&xdefn_len,
" stk%d = %s %c %s;\n",
stacksz-1,operand,op,operand2 ))
return -1;
--stacksz;
// account for the max intermediate result on the stack.
if (stacksz > max_stacksz) max_stacksz = stacksz;
stack[stacksz-1] = '\0';
break;
case 'n':
mk_operand(operand,sizeof(operand),stack,stacksz-1);
if (apprintf(defn,sizeof(defn),&defn_len,
" stk%d = ~%s;\n",
stacksz,operand ))
return -1;
mk_xoperand(operand,sizeof(operand),stack,stacksz-1);
if (apprintf(xdefn,sizeof(xdefn),&xdefn_len,
" stk%d = ~%s;\n",
stacksz,operand ))
return -1;
// account for the max intermediate result on the stack.
if (stacksz > max_stacksz) max_stacksz = stacksz;
stack[stacksz-1] = '\0';
break;
default:
fprintf (stderr,"Illegal character %c in rop string %s.\n",
*c,ropstr);
return -1;
}
if (stacksz!=1)
{
fprintf (stderr,"Unbalanced shift/reduce in rop string %s.\n",ropstr);
return -1;
}
mk_operand(operand,sizeof(operand),stack,0);
// ******** normal ROP functions
// case 1: source/pattern opaque.
fprintf (out,
"/* %s source/pattern opaque. */\n"
"static void rop3_%d_0_0 (unsigned char *D, unsigned char S, unsigned char T)\n{\n",
ropstr,irop);
for (i=1;i<=max_stacksz;++i)
fprintf(out," unsigned char stk%d;\n",i);
fputs(defn,out);
// optimize for noop.
if (stack[0] != 'D')
fprintf(out," *D = %s;\n",operand);
fprintf(out,"}\n\n");
// case 2: source opaque/pattern transparent.
fprintf (out,
"/* %s source opaque/pattern transparent. */\n"
"static void rop3_%d_0_1 (unsigned char *D, unsigned char S, unsigned char T)\n{\n",
ropstr,irop);
for (i=1;i<=max_stacksz;++i)
fprintf(out," unsigned char stk%d;\n",i);
fputs(defn,out);
// Image_A = Temporary_ROP3, & Not Src.
// Image_B = Temporary_ROP3 & Pattern.
// Image_C = Not Pattern & Src & Dest.
// Return Image_A | Image_B | Image_C
fprintf(out," *D = (%s & S) | (%s & (~T)) | (T & (~S) & *D);\n",operand,operand);
fprintf(out,"}\n\n");
// case 3: source transparent/pattern opaque.
fprintf (out,
"/* %s source transparent/pattern opaque. */\n"
"static void rop3_%d_1_0 (unsigned char *D, unsigned char S, unsigned char T)\n{\n",
ropstr,irop);
for (i=1;i<=max_stacksz;++i)
fprintf(out," unsigned char stk%d;\n",i);
fputs(defn,out);
// Image_A = Temporary_ROP3 & Src.
// Image_B = Dest & Not Src.
// Return Image_A | Image_B
fprintf(out," *D = (%s & (~S)) | (*D & S);\n",operand);
fprintf(out,"}\n\n");
// case 4: source/pattern transparent.
fprintf (out,
"/* %s source/pattern transparent. */\n"
"static void rop3_%d_1_1 (unsigned char *D, unsigned char S, unsigned char T)\n{\n",
ropstr,irop);
for (i=1;i<=max_stacksz;++i)
fprintf(out," unsigned char stk%d;\n",i);
fputs(defn,out);
// Image_A = Temporary_ROP3 & Src & Pattern.
// Image_B = Dest & Not Src.
// Image_C = Dest & Not Pattern.
// Return Image_A | Image_B | Image_C.
fprintf(out," *D = (%s & (~S) & (~T)) | (*D & S) | (*D & T);\n",operand);
fprintf(out,"}\n\n");
// ******** ROP transfer functions
mk_xoperand(operand,sizeof(operand),stack,0);
// case 1: source/pattern opaque.
fprintf (out,
"/* %s source/pattern opaque. */\n"
"static unsigned xrop3_%d_0_0 (unsigned char s, unsigned char t)\n{\n",
ropstr,irop);
if (D_used)
fprintf (out," unsigned D = 0x00ff;\n");
if (S_used)
fprintf (out," unsigned S = ((unsigned)s << 8) | s;\n");
if (T_used)
fprintf (out," unsigned T = ((unsigned)t << 8) | t;\n");
for (i=1;i<=max_stacksz;++i)
fprintf(out," unsigned stk%d;\n",i);
fputs(xdefn,out);
fprintf(out," return %s;\n",operand);
fprintf(out,"}\n\n");
// case 2: source opaque/pattern transparent.
fprintf (out,
"/* %s source opaque/pattern transparent. */\n"
"static unsigned xrop3_%d_0_1 (unsigned char s, unsigned char t)\n{\n",
ropstr,irop);
fprintf (out," unsigned D = 0x00ff;\n");
fprintf (out," unsigned S = ((unsigned)s << 8) | s;\n");
fprintf (out," unsigned T = ((unsigned)t << 8) | t;\n");
for (i=1;i<=max_stacksz;++i)
fprintf(out," unsigned stk%d;\n",i);
fputs(xdefn,out);
// Image_A = Temporary_ROP3, & Not Src.
// Image_B = Temporary_ROP3 & Pattern.
// Image_C = Not Pattern & Src & Dest.
// Return Image_A | Image_B | Image_C
fprintf(out," return (%s & S) | (%s & (~T)) | (T & (~S) & D);\n",operand,operand);
fprintf(out,"}\n\n");
// case 3: source transparent/pattern opaque.
fprintf (out,
"/* %s source transparent/pattern opaque. */\n"
"static unsigned xrop3_%d_1_0 (unsigned char s, unsigned char t)\n{\n",
ropstr,irop);
fprintf (out," unsigned D = 0x00ff;\n");
fprintf (out," unsigned S = ((unsigned)s << 8) | s;\n");
if (T_used)
fprintf (out," unsigned T = ((unsigned)t << 8) | t;\n");
for (i=1;i<=max_stacksz;++i)
fprintf(out," unsigned stk%d;\n",i);
fputs(xdefn,out);
// Image_A = Temporary_ROP3 & Src.
// Image_B = Dest & Not Src.
// Return Image_A | Image_B
fprintf(out," return (%s & (~S)) | (D & S);\n",operand);
fprintf(out,"}\n\n");
// case 4: source/pattern transparent.
fprintf (out,
"/* %s source/pattern transparent. */\n"
"static unsigned xrop3_%d_1_1 (unsigned char s, unsigned char t)\n{\n",
ropstr,irop);
fprintf (out," unsigned D = 0x00ff;\n");
fprintf (out," unsigned S = ((unsigned)s << 8) | s;\n");
fprintf (out," unsigned T = ((unsigned)t << 8) | t;\n");
for (i=1;i<=max_stacksz;++i)
fprintf(out," unsigned stk%d;\n",i);
fputs(xdefn,out);
// Image_A = Temporary_ROP3 & Src & Pattern.
// Image_B = Dest & Not Src.
// Image_C = Dest & Not Pattern.
// Return Image_A | Image_B | Image_C.
fprintf(out," return (%s & (~S) & (~T)) | (D & S) | (D & T);\n",operand);
fprintf(out,"}\n\n");
return 0;
}
int main (int argc, const char *argv[])
{
FILE *in=0;
FILE *out=0;
int irop=0,i;
char ropstr[32];
int ret = 0;
time_t now;
if (argc != 3)
{
fprintf(stderr,"usage: %s <in> <out>.\n",argv[0]);
return 1;
}
in = fopen(argv[1],"rb");
if (!in)
{
fprintf(stderr,"%s: Error opening file <%s>: %s.\n",
argv[0],argv[1],strerror(errno));
ret = 1;
goto cleanup;
}
out = fopen(argv[2],"wb");
if (!out)
{
fprintf(stderr,"%s: Error opening file <%s>: %s.\n",
argv[0],argv[2],strerror(errno));
ret = 1;
goto cleanup;
}
now = time(0);
fprintf(out,"/* Generated automatically by %s at %.24s.\n",argv[0],ctime(&now));
fprintf(out," Do not edit!\n");
fprintf(out," */\n");
fprintf(out,"#include <hpgs.h>\n\n");
// go through all ROP descritions in hpgsrop.dat
while (fscanf(in,"%d %31s",&i,ropstr) == 2)
{
if (i!=irop)
{
fprintf(stderr,"%s: Illegal count %d in stanza %d.\n",
argv[0],i,irop);
ret = 1;
goto cleanup;
}
if (write_rop3_func(out,irop,ropstr))
goto cleanup;
++irop;
}
// Collect all rop function in one big lookup table...
fprintf(out,
"static hpgs_rop3_func_t rop3_table[][2][2] = {\n");
for (i=0;i<irop;++i)
fprintf(out,
" {{rop3_%d_0_0,rop3_%d_0_1},{rop3_%d_1_0,rop3_%d_1_1}}%s\n",
i,i,i,i,i<irop-1 ? "," : "");
fprintf(out,
"};\n\n");
// generate our public interface hpgs_rop3_func.
fprintf(out,
"hpgs_rop3_func_t hpgs_rop3_func(int rop3,\n"
" hpgs_bool src_transparency,\n"
" hpgs_bool pattern_transparency)\n"
"{\n"
" if (rop3 < 0 || rop3 >= %d) return 0;\n"
" return rop3_table[rop3][src_transparency!=0][pattern_transparency!=0];\n"
"}\n",
irop);
// Collect all rop xfer function in one big lookup table...
fprintf(out,
"static hpgs_xrop3_func_t xrop3_table[][2][2] = {\n");
for (i=0;i<irop;++i)
fprintf(out,
" {{xrop3_%d_0_0,xrop3_%d_0_1},{xrop3_%d_1_0,xrop3_%d_1_1}}%s\n",
i,i,i,i,i<irop-1 ? "," : "");
fprintf(out,
"};\n\n");
// generate our public interface hpgs_xrop3_func.
fprintf(out,
"hpgs_xrop3_func_t hpgs_xrop3_func(int rop3,\n"
" hpgs_bool src_transparency,\n"
" hpgs_bool pattern_transparency)\n"
"{\n"
" if (rop3 < 0 || rop3 >= %d) return 0;\n"
" return xrop3_table[rop3][src_transparency!=0][pattern_transparency!=0];\n"
"}\n",
irop);
cleanup:
if (in) fclose(in);
if (out) fclose(out);
return ret;
}

View File

@ -0,0 +1,84 @@
/***********************************************************************
* *
* $Id: hpgsmutex.h 286 2006-03-03 15:14:14Z softadm $
* *
* hpgs - HPGl Script, a hpgl/2 interpreter, which uses a Postscript *
* API for rendering a scene and thus renders to a variety of *
* devices and fileformats. *
* *
* (C) 2004-2006 ev-i Informationstechnologie GmbH http://www.ev-i.at *
* *
* Author: Wolfgang Glas *
* *
* hpgs is free software; you can redistribute it and/or *
* modify it under the terms of the GNU Lesser General Public *
* License as published by the Free Software Foundation; either *
* version 2.1 of the License, or (at your option) any later version. *
* *
* hpgs is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU *
* Lesser General Public License for more details. *
* *
* You should have received a copy of the GNU Lesser General Public *
* License along with this library; if not, write to the *
* Free Software Foundation, Inc., 59 Temple Place, Suite 330, *
* Boston, MA 02111-1307 USA *
* *
***********************************************************************
* *
* Private header file for thread mutex support. *
* *
***********************************************************************/
#ifndef __HPGS_MUTEX_H__
#define __HPGS_MUTEX_H__
#ifndef __HPGS_H
#include <hpgs.h>
#endif
#ifdef WIN32
#include <windows.h>
typedef CRITICAL_SECTION hpgs_mutex_t;
#else
#include <pthread.h>
typedef pthread_mutex_t hpgs_mutex_t;
#endif
static void hpgs_mutex_init(hpgs_mutex_t *m);
static void hpgs_mutex_destroy(hpgs_mutex_t *m);
static void hpgs_mutex_lock(hpgs_mutex_t *m);
static void hpgs_mutex_unlock(hpgs_mutex_t *m);
#ifdef WIN32
__inline__ void hpgs_mutex_init(hpgs_mutex_t *m)
{ InitializeCriticalSection(m); }
__inline__ void hpgs_mutex_destroy(hpgs_mutex_t *m)
{ DeleteCriticalSection(m); }
__inline__ void hpgs_mutex_lock(hpgs_mutex_t *m)
{ EnterCriticalSection(m); }
__inline__ void hpgs_mutex_unlock(hpgs_mutex_t *m)
{ LeaveCriticalSection(m); }
#else
__inline__ void hpgs_mutex_init(hpgs_mutex_t *m)
{ pthread_mutex_init(m,0); }
__inline__ void hpgs_mutex_destroy(hpgs_mutex_t *m)
{ pthread_mutex_destroy(m); }
__inline__ void hpgs_mutex_lock(hpgs_mutex_t *m)
{ pthread_mutex_lock(m); }
__inline__ void hpgs_mutex_unlock(hpgs_mutex_t *m)
{ pthread_mutex_unlock(m); }
#endif
#endif

View File

@ -0,0 +1,343 @@
/***********************************************************************
* *
* $Id: hpgsostream.c 368 2006-12-31 15:18:08Z softadm $
* *
* hpgs - HPGl Script, a hpgl/2 interpreter, which uses a Postscript *
* API for rendering a scene and thus renders to a variety of *
* devices and fileformats. *
* *
* (C) 2004-2006 ev-i Informationstechnologie GmbH http://www.ev-i.at *
* *
* Author: Wolfgang Glas *
* *
* hpgs is free software; you can redistribute it and/or *
* modify it under the terms of the GNU Lesser General Public *
* License as published by the Free Software Foundation; either *
* version 2.1 of the License, or (at your option) any later version. *
* *
* hpgs is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU *
* Lesser General Public License for more details. *
* *
* You should have received a copy of the GNU Lesser General Public *
* License along with this library; if not, write to the *
* Free Software Foundation, Inc., 59 Temple Place, Suite 330, *
* Boston, MA 02111-1307 USA *
* *
***********************************************************************
* *
* The implementation of basic output streams. *
* *
***********************************************************************/
#include<hpgs.h>
#include<string.h>
#include<stdarg.h>
/*! The counterpart of ANSI fprintf for \c hpgs_ostream. */
int hpgs_ostream_printf (hpgs_ostream *_this, const char *msg, ...)
{
int ret;
va_list ap;
va_start(ap,msg);
ret=_this->vtable->vprintf_func(_this->stream,msg,ap);
va_end(ap);
return ret;
}
/*! The counterpart of ANSI fvprintf for \c hpgs_ostream. */
int hpgs_ostream_vprintf (hpgs_ostream *_this, const char *msg, va_list ap)
{
int ret;
va_list aq;
va_copy(aq, ap);
ret = _this->vtable->vprintf_func(_this->stream,msg,aq);
va_end(aq);
return ret;
}
static int file_seek (FILE *file, size_t pos)
{
return fseek(file,pos,SEEK_SET);
}
static int file_tell (FILE *file, int layer, size_t *pos)
{
if (layer) return -1;
long pp=ftell(file);
if (pp<0) return -1;
*pos = pp;
return 0;
}
static hpgs_ostream_vtable stdfile_vtable =
{
(hpgs_ostream_putc_func_t) putc,
(hpgs_ostream_write_func_t) fwrite,
(hpgs_ostream_vprintf_func_t) vfprintf,
(hpgs_ostream_flush_func_t) fflush,
(hpgs_ostream_close_func_t) fflush,
(hpgs_ostream_iserror_func_t) ferror,
(hpgs_ostream_getbuf_func_t) 0,
(hpgs_ostream_tell_func_t) file_tell,
(hpgs_ostream_seek_func_t) 0
};
static hpgs_ostream_vtable file_vtable =
{
(hpgs_ostream_putc_func_t) putc,
(hpgs_ostream_write_func_t) fwrite,
(hpgs_ostream_vprintf_func_t) vfprintf,
(hpgs_ostream_flush_func_t) fflush,
(hpgs_ostream_close_func_t) fclose,
(hpgs_ostream_iserror_func_t) ferror,
(hpgs_ostream_getbuf_func_t) 0,
(hpgs_ostream_tell_func_t) file_tell,
(hpgs_ostream_seek_func_t) file_seek
};
/*! Returns a new \c hpgs_ostream created on the heap,
which operates on a file, which is opened by this call
in write-only mode.
Returns a null pointer, when an I/O error occurrs.
In this case, details about the the error can be retrieved
using \c errno.
*/
hpgs_ostream *hpgs_new_file_ostream (const char *fn)
{
FILE *out = fn ? fopen (fn,"wb") : stdout;
hpgs_ostream *ret = 0;
if (!out) return 0;
ret = (hpgs_ostream *)malloc(sizeof(hpgs_ostream));
if (!ret)
{
fclose(out);
return 0;
}
ret->stream = out;
if (fn)
ret->vtable = &file_vtable;
else
ret->vtable = &stdfile_vtable;
return ret;
}
typedef struct hpgs_mem_ostream_stream_st hpgs_mem_ostream_stream;
struct hpgs_mem_ostream_stream_st
{
unsigned char *data;
unsigned char *pptr;
unsigned char *eptr;
int errflg;
};
static int mem_grow (hpgs_mem_ostream_stream *stream, size_t hint)
{
if (stream->errflg)
return EOF;
size_t pos = stream->pptr-stream->data;
size_t sz = stream->eptr-stream->data;
size_t sz2 = (hint > sz) ? sz+hint : 2*sz;
// check for overflow.
if (sz2 < sz)
{
stream->errflg = 1;
return EOF;
}
unsigned char *ndata=(unsigned char *)realloc(stream->data,sz2);
if (ndata)
{
stream->data=ndata;
stream->pptr=stream->data+pos;
stream->eptr=stream->data+sz2;
return 0;
}
else
{
stream->errflg = 1;
return EOF;
}
}
static int mem_putc (int c, hpgs_mem_ostream_stream *stream)
{
if (stream->pptr >= stream->eptr)
mem_grow(stream,0);
if (stream->errflg)
return EOF;
*stream->pptr = c;
++stream->pptr;
return c & 0xff;
}
static size_t mem_write (void *ptr, size_t size, size_t nmemb, hpgs_mem_ostream_stream *stream)
{
if (stream->pptr + size*nmemb > stream->eptr)
mem_grow(stream,size*nmemb);
if (stream->errflg)
return 0;
memcpy(stream->pptr,ptr,size*nmemb);
stream->pptr += size*nmemb;
return nmemb;
}
static int mem_vprintf (hpgs_mem_ostream_stream *stream, const char *fmt, va_list ap)
{
int n;
size_t size;
while (1)
{
if (stream->errflg)
return EOF;
size = stream->eptr - stream->pptr;
/* Try to print in the allocated space. */
va_list aq;
va_copy(aq, ap);
#ifdef WIN32
n = _vsnprintf (stream->pptr, size, fmt, aq);
#else
n = vsnprintf ((char*)stream->pptr, size, fmt, aq);
#endif
va_end(aq);
/* If that worked, return the string. */
if (n > -1 && n < size)
{
stream->pptr += n;
return n;
}
/* Else try again with more space. */
mem_grow(stream,0);
}
return 0;
}
static int mem_close (hpgs_mem_ostream_stream *stream)
{
if (stream->data) free(stream->data);
free(stream);
return 0;
}
static int mem_iserror (hpgs_mem_ostream_stream *stream)
{
return stream->errflg;
}
static hpgs_istream *mem_getbuf (hpgs_mem_ostream_stream *stream)
{
if (stream->errflg || !stream->data)
return 0;
return hpgs_new_mem_istream (stream->data,stream->pptr-stream->data,HPGS_FALSE);
}
static int mem_tell (hpgs_mem_ostream_stream *stream, int layer, size_t *pos)
{
if (layer || stream->errflg) return -1;
*pos = stream->pptr-stream->data;
return 0;
}
static int mem_seek (hpgs_mem_ostream_stream *stream, size_t pos)
{
if (stream->errflg) return -1;
if (stream->data + pos > stream->pptr)
{
stream->errflg = 1;
return -1;
}
stream->pptr = stream->data + pos;
return 0;
}
static hpgs_ostream_vtable mem_vtable =
{
(hpgs_ostream_putc_func_t) mem_putc,
(hpgs_ostream_write_func_t) mem_write,
(hpgs_ostream_vprintf_func_t) mem_vprintf,
(hpgs_ostream_flush_func_t) 0,
(hpgs_ostream_close_func_t) mem_close,
(hpgs_ostream_iserror_func_t) mem_iserror,
(hpgs_ostream_getbuf_func_t) mem_getbuf,
(hpgs_ostream_tell_func_t) mem_tell,
(hpgs_ostream_seek_func_t) mem_seek
};
/*! Returns a new \c hpgs_ostream created on the heap,
which operates on a malloced chunk of memory with
the preallocated given size.
The memory buffer is realloced when the data grows over the
given preallocated size.
Returns a null pointer, when the system is out of memory.
*/
hpgs_ostream *hpgs_new_mem_ostream (size_t data_reserve)
{
hpgs_mem_ostream_stream *stream;
hpgs_ostream *ret = (hpgs_ostream *)malloc(sizeof(hpgs_ostream));
if (!ret)
return 0;
stream =
(hpgs_mem_ostream_stream *)malloc(sizeof(hpgs_mem_ostream_stream));
if (!stream)
{
free (ret);
return 0;
}
stream->data = (unsigned char *)malloc(data_reserve);
stream->pptr = stream->data;
stream->eptr = stream->data ? stream->data+data_reserve : 0;
stream->errflg = stream->data ? 0 : 1;
ret->stream = stream;
ret->vtable = &mem_vtable;
return ret;
}
int hpgs_copy_streams (hpgs_ostream *out, hpgs_istream *in)
{
unsigned char buf[16384];
size_t sz;
while ((sz = hpgs_istream_read(buf,1,sizeof(buf),in)) > 0)
if (hpgs_ostream_write(buf,1,sz,out) == 0)
return -1;
return hpgs_istream_iserror(in);
}

View File

@ -0,0 +1,716 @@
/***********************************************************************
* *
* $Id: hpgspaint.c 375 2007-01-24 16:22:49Z softadm $
* *
* hpgs - HPGl Script, a hpgl/2 interpreter, which uses a Postscript *
* API for rendering a scene and thus renders to a variety of *
* devices and fileformats. *
* *
* (C) 2004-2006 ev-i Informationstechnologie GmbH http://www.ev-i.at *
* *
* Author: Wolfgang Glas *
* *
* hpgs is free software; you can redistribute it and/or *
* modify it under the terms of the GNU Lesser General Public *
* License as published by the Free Software Foundation; either *
* version 2.1 of the License, or (at your option) any later version. *
* *
* hpgs is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU *
* Lesser General Public License for more details. *
* *
* You should have received a copy of the GNU Lesser General Public *
* License along with this library; if not, write to the *
* Free Software Foundation, Inc., 59 Temple Place, Suite 330, *
* Boston, MA 02111-1307 USA *
* *
***********************************************************************
* *
* The implementation of the public API for the pixel painter. *
* *
***********************************************************************/
#include<hpgspaint.h>
#include<math.h>
#include<assert.h>
#include<string.h>
#if defined ( __MINGW32__ ) || defined ( _MSC_VER )
#include <malloc.h>
#else
#include <alloca.h>
#endif
//#define HPGS_PAINT_DEBUG_ROP3
/*! \defgroup paint_device Paint device.
This module contains the workhorse for rendering a scenery to pixel
graphics, \c hpgs_paint_device.
Most notably, you can call \c hpgs_new_paint_device in order to
create a new paint device and perform the usual operations
\c hpgs_moveto, \c hpgs_lineto, ... on it.
Details about the implementation are explained in the documentation
of \c hpgs_paint_device_st and \c hpgs_paint_clipper_st and the
hpyerlinks therein.
*/
/* static paint device methods for the hpgs_device vtable. */
static int pdv_moveto (hpgs_device *_this, const hpgs_point *p)
{
hpgs_paint_device *pdv = (hpgs_paint_device *)_this;
if (hpgs_paint_path_moveto(pdv->path,p))
return hpgs_set_error(hpgs_i18n("moveto error."));
return 0;
}
static int pdv_lineto (hpgs_device *_this, const hpgs_point *p)
{
hpgs_paint_device *pdv = (hpgs_paint_device *)_this;
if (hpgs_paint_path_lineto(pdv->path,p))
return hpgs_set_error(hpgs_i18n("lineto error."));
return 0;
}
static int pdv_curveto (hpgs_device *_this, const hpgs_point *p1,
const hpgs_point *p2, const hpgs_point *p3 )
{
hpgs_paint_device *pdv = (hpgs_paint_device *)_this;
if (hpgs_paint_path_curveto(pdv->path,p1,p2,p3))
return hpgs_set_error(hpgs_i18n("curveto error."));
return 0;
}
static int pdv_newpath (hpgs_device *_this)
{
hpgs_paint_device *pdv = (hpgs_paint_device *)_this;
hpgs_paint_path_truncate(pdv->path);
return 0;
}
static int pdv_closepath (hpgs_device *_this)
{
hpgs_paint_device *pdv = (hpgs_paint_device *)_this;
if (hpgs_paint_path_closepath(pdv->path))
return hpgs_set_error(hpgs_i18n("closepath error."));
return 0;
}
static int pdv_stroke (hpgs_device *_this)
{
hpgs_paint_device *pdv = (hpgs_paint_device *)_this;
int ret = 0;
if (pdv->path->n_points > 1 ||
(pdv->path->n_points == 1 && (pdv->path->points[0].flags&HPGS_POINT_DOT))
)
{
if (!pdv->overscan &&
pdv->gstate->linewidth < 1.5 * pdv->path_clipper->yfac)
{
const hpgs_paint_clipper *clip = pdv->clippers[pdv->current_clipper];
if (hpgs_paint_clipper_thin_cut(pdv->path_clipper,
pdv->path,pdv->gstate))
return hpgs_set_error(hpgs_i18n("Out of memory cutting thin line."));
if (hpgs_paint_clipper_emit(pdv->image,
pdv->path_clipper,clip,
&pdv->color,1,1))
{
if (hpgs_have_error())
return hpgs_error_ctxt(hpgs_i18n("stroke: Image error"));
return hpgs_set_error(hpgs_i18n("stroke: Error emitting scanlines."));
}
hpgs_paint_clipper_clear(pdv->path_clipper);
}
else
{
hpgs_paint_path *p = hpgs_paint_path_stroke_path(pdv->path,
pdv->gstate);
if (!p)
return hpgs_set_error(hpgs_i18n("Out of memory creating stroke path."));
ret = hpgs_paint_device_fill(pdv,p,HPGS_TRUE,HPGS_TRUE);
hpgs_paint_path_destroy(p);
}
}
hpgs_paint_path_truncate(pdv->path);
if (ret)
return hpgs_set_error(hpgs_i18n("Error filling stroke path."));
return 0;
}
static int pdv_fill (hpgs_device *_this, hpgs_bool winding)
{
hpgs_paint_device *pdv = (hpgs_paint_device *)_this;
int ret = hpgs_paint_device_fill(pdv,pdv->path,winding,HPGS_FALSE);
hpgs_paint_path_truncate(pdv->path);
return ret;
}
static int pdv_clip (hpgs_device *_this, hpgs_bool winding)
{
hpgs_paint_device *pdv = (hpgs_paint_device *)_this;
int ret = hpgs_paint_device_clip(pdv,pdv->path,winding);
hpgs_paint_path_truncate(pdv->path);
return ret;
}
static int pdv_clipsave (hpgs_device *_this)
{
hpgs_paint_device *pdv = (hpgs_paint_device *)_this;
if (pdv->clip_depth >= HPGS_PAINT_MAX_CLIP_DEPTH)
return hpgs_set_error(hpgs_i18n("Maximum clip depth of %d exceeded."),
HPGS_PAINT_MAX_CLIP_DEPTH);
pdv->clippers[pdv->clip_depth] = 0;
++pdv->clip_depth;
return 0;
}
static int pdv_cliprestore (hpgs_device *_this)
{
hpgs_paint_device *pdv = (hpgs_paint_device *)_this;
--pdv->clip_depth;
if (pdv->clippers[pdv->clip_depth])
{
hpgs_paint_clipper_destroy(pdv->clippers[pdv->clip_depth]);
pdv->clippers[pdv->clip_depth] = 0;
}
if (pdv->current_clipper < pdv->clip_depth)
return 0;
while (pdv->current_clipper > 0)
{
--pdv->current_clipper;
if (pdv->clippers[pdv->current_clipper])
return 0;
}
return hpgs_set_error(hpgs_i18n("cliprestore: No valid clipper found."));
}
static int pdv_setrgbcolor (hpgs_device *_this, const hpgs_color *rgb)
{
hpgs_paint_device *pdv = (hpgs_paint_device *)_this;
pdv->gstate->color = *rgb;
pdv->color.r = (unsigned char)(rgb->r*255.0);
pdv->color.g = (unsigned char)(rgb->g*255.0);
pdv->color.b = (unsigned char)(rgb->b*255.0);
if (hpgs_image_define_color(pdv->image,&pdv->color))
return hpgs_error_ctxt("setrgbcolor");
pdv->gstate->pattern_color = *rgb;
hpgs_palette_color patcol;
patcol.r = pdv->color.r & (~pdv->patcol.r);
patcol.g = pdv->color.g & (~pdv->patcol.g);
patcol.b = pdv->color.b & (~pdv->patcol.b);
#ifdef HPGS_PAINT_DEBUG_ROP3
hpgs_log("setrgbcol: patcol=%d,%d,%d.\n",patcol.r,patcol.g,patcol.b);
#endif
return hpgs_image_setpatcol(pdv->image,&patcol);
}
static int pdv_setdash (hpgs_device *_this, const float *segs,
unsigned n, double d)
{
hpgs_paint_device *pdv = (hpgs_paint_device *)_this;
if (hpgs_gstate_setdash(pdv->gstate,segs,n,d))
return hpgs_set_error(hpgs_i18n("setdash: Out of memory."));
return 0;
}
static int pdv_setlinewidth(hpgs_device *_this, double lw)
{
hpgs_paint_device *pdv = (hpgs_paint_device *)_this;
if (lw < pdv->thin_alpha * pdv->path_clipper->yfac)
pdv->gstate->linewidth = pdv->thin_alpha * pdv->path_clipper->yfac;
else
pdv->gstate->linewidth = lw;
return 0;
}
static int pdv_setlinecap (hpgs_device *_this, hpgs_line_cap lc)
{
hpgs_paint_device *pdv = (hpgs_paint_device *)_this;
pdv->gstate->line_cap = lc;
return 0;
}
static int pdv_setlinejoin (hpgs_device *_this, hpgs_line_join lj)
{
hpgs_paint_device *pdv = (hpgs_paint_device *)_this;
pdv->gstate->line_join = lj;
return 0;
}
static int pdv_setmiterlimit (hpgs_device *_this, double l)
{
hpgs_paint_device *pdv = (hpgs_paint_device *)_this;
pdv->gstate->miterlimit = l;
return 0;
}
static int pdv_setrop3 (hpgs_device *_this, int rop,
hpgs_bool src_transparency, hpgs_bool pattern_transparency)
{
hpgs_paint_device *pdv = (hpgs_paint_device *)_this;
hpgs_rop3_func_t rop3;
#ifdef HPGS_PAINT_DEBUG_ROP3
hpgs_log("setrop3: rop,src_trans,pat_trans=%d,%d,%d.\n",
rop,src_transparency,pattern_transparency);
#endif
pdv->gstate->rop3 = rop;
pdv->gstate->src_transparency = src_transparency;
pdv->gstate->pattern_transparency = pattern_transparency;
rop3 = hpgs_rop3_func(rop,src_transparency,pattern_transparency);
if (!rop3)
return hpgs_set_error(hpgs_i18n("setrop3: Invalid ROP3 %d specified"),rop);
return hpgs_image_setrop3(pdv->image,rop3);
}
static int pdv_setpatcol(hpgs_device *_this, const hpgs_color *rgb)
{
hpgs_paint_device *pdv = (hpgs_paint_device *)_this;
pdv->gstate->pattern_color = *rgb;
pdv->patcol.r = (unsigned char)(rgb->r * 255.0);
pdv->patcol.g = (unsigned char)(rgb->g * 255.0);
pdv->patcol.b = (unsigned char)(rgb->b * 255.0);
hpgs_palette_color patcol;
patcol.r = pdv->color.r & (~pdv->patcol.r);
patcol.g = pdv->color.g & (~pdv->patcol.g);
patcol.b = pdv->color.b & (~pdv->patcol.b);
#ifdef HPGS_PAINT_DEBUG_ROP3
hpgs_log("setpatcol: patcol=%d,%d,%d.\n",patcol.r,patcol.g,patcol.b);
#endif
return hpgs_image_setpatcol(pdv->image,&patcol);
}
static int pdv_drawimage(hpgs_device *_this,
const hpgs_image *img,
const hpgs_point *ll, const hpgs_point *lr,
const hpgs_point *ur)
{
hpgs_paint_device *pdv = (hpgs_paint_device *)_this;
if (!img)
return hpgs_set_error(hpgs_i18n("drawimage: Null image specified."));
hpgs_palette_color patcol;
patcol.r = 0;
patcol.g = 0;
patcol.b = 0;
if (hpgs_image_setpatcol(pdv->image,&patcol))
return -1;
if (hpgs_paint_device_drawimage(pdv,img,ll,lr,ur))
{
if (hpgs_have_error())
return hpgs_error_ctxt(hpgs_i18n("drawimage error"));
return hpgs_set_error(hpgs_i18n("drawimage error."));
}
patcol.r = pdv->color.r & (~pdv->patcol.r);
patcol.g = pdv->color.g & (~pdv->patcol.g);
patcol.b = pdv->color.b & (~pdv->patcol.b);
#ifdef HPGS_PAINT_DEBUG_ROP3
hpgs_log("setpatcol: patcol=%d,%d,%d.\n",patcol.r,patcol.g,patcol.b);
#endif
return hpgs_image_setpatcol(pdv->image,&patcol);
}
static int pdv_showpage (hpgs_device *_this, int i)
{
hpgs_paint_device *pdv = (hpgs_paint_device *)_this;
int ret = 0;
if (i>0 && pdv->filename)
{
int l = strlen(pdv->filename);
char *fn = hpgs_alloca(l+20);
char * dot = strrchr(pdv->filename,'.');
int pos = dot ? dot-pdv->filename : l;
#ifdef WIN32
_snprintf(fn,l+20,"%.*s%4.4d%s",
pos,pdv->filename,i,pdv->filename+pos);
#else
snprintf(fn,l+20,"%.*s%4.4d%s",
pos,pdv->filename,i,pdv->filename+pos);
#endif
ret = hpgs_image_write(pdv->image,fn);
if (ret == 0)
ret = hpgs_image_clear(pdv->image);
}
else if (pdv->filename == 0 || strlen(pdv->filename) > 0)
ret = hpgs_image_write(pdv->image,pdv->filename);
return ret;
}
static int pdv_setplotsize (hpgs_device *_this, const hpgs_bbox *bb)
{
hpgs_paint_device *pdv = (hpgs_paint_device *)_this;
int i;
if (hpgs_bbox_isequal(&pdv->page_bb,bb))
return 0;
int w = (int)ceil((bb->urx-bb->llx)*pdv->xres);
int h = (int)ceil((bb->ury-bb->lly)*pdv->yres);
if (w<2 || h<2)
return hpgs_set_error(hpgs_i18n("setplotsize: The given bounding box result in a null image."));
if (hpgs_image_resize(pdv->image,w,h))
return hpgs_error_ctxt(hpgs_i18n("setplotsize: error resizing image"));
if (pdv->path_clipper) hpgs_paint_clipper_destroy(pdv->path_clipper);
pdv->path_clipper = hpgs_new_paint_clipper(bb,
pdv->image->height,
16,pdv->overscan);
if (!pdv->path_clipper)
return hpgs_set_error(hpgs_i18n("setplotsize: Out of memory allocating path clipper."));
for (i=0;i<pdv->clip_depth;++i)
{
if (pdv->clippers[i]) hpgs_paint_clipper_destroy(pdv->clippers[i]);
pdv->clippers[i]=0;
}
// Initial dimension of clip segments is 4.
pdv->clippers[0] = hpgs_new_paint_clipper(bb,
pdv->image->height,4,pdv->overscan);
if (!pdv->clippers[0])
return hpgs_set_error(hpgs_i18n("setplotsize: Out of memory allocating clip clipper."));
if (hpgs_paint_clipper_reset(pdv->clippers[0],bb->llx,bb->urx))
return hpgs_set_error(hpgs_i18n("setplotsize: Out of memory initializing clip clipper."));
pdv->clip_depth = 1;
pdv->current_clipper = 0;
return 0;
}
static int pdv_capabilities (hpgs_device *_this)
{
hpgs_paint_device *pdv = (hpgs_paint_device *)_this;
int ret =
HPGS_DEVICE_CAP_RASTER |
HPGS_DEVICE_CAP_MULTIPAGE |
HPGS_DEVICE_CAP_MULTISIZE |
HPGS_DEVICE_CAP_DRAWIMAGE;
if (pdv->overscan)
ret |= HPGS_DEVICE_CAP_ANTIALIAS;
if (pdv->image->vtable->setrop3)
ret |= HPGS_DEVICE_CAP_ROP3;
return ret;
}
static void pdv_destroy (hpgs_device *_this)
{
hpgs_paint_device *pdv = (hpgs_paint_device *)_this;
int i;
if (pdv->filename) free(pdv->filename);
if (pdv->path) hpgs_paint_path_destroy(pdv->path);
if (pdv->path_clipper) hpgs_paint_clipper_destroy(pdv->path_clipper);
if (pdv->gstate) hpgs_gstate_destroy(pdv->gstate);
if (pdv->image) hpgs_image_destroy(pdv->image);
for (i=0;i<pdv->clip_depth;++i)
if (pdv->clippers[i]) hpgs_paint_clipper_destroy(pdv->clippers[i]);
}
static hpgs_device_vtable pdv_vtable =
{
"hpgs_paint_device",
pdv_moveto,
pdv_lineto,
pdv_curveto,
pdv_newpath,
pdv_closepath,
pdv_stroke,
pdv_fill,
pdv_clip,
pdv_clipsave,
pdv_cliprestore,
pdv_setrgbcolor,
pdv_setdash,
pdv_setlinewidth,
pdv_setlinecap,
pdv_setlinejoin,
pdv_setmiterlimit,
pdv_setrop3,
pdv_setpatcol,
pdv_drawimage,
pdv_setplotsize,
0 /* pdv_getplotsize */,
pdv_showpage,
0 /* pdv_finish */,
pdv_capabilities,
pdv_destroy
};
/*! Creates a new paint device on the heap.
Use \c hpgs_destroy in order to destroy the returned
device pointer.
The bounding box, which is mapped onto the given \c image is passed
in as well as the \c antialiasing switch.
A null pointer is returned, if the system is out of memory.
*/
hpgs_paint_device *hpgs_new_paint_device(hpgs_image *image,
const char *filename,
const hpgs_bbox *bb,
hpgs_bool antialias )
{
hpgs_paint_device *ret=(hpgs_paint_device *)malloc(sizeof(hpgs_paint_device));
if (ret)
{
ret->image = image;
ret->path = 0;
ret->gstate = 0;
ret->overscan = antialias;
ret->thin_alpha = 0.25;
if (filename)
{
ret->filename = strdup(filename);
if (!ret->filename) goto fatal_error;
}
else
ret->filename = 0;
memset(ret->clippers,
0,HPGS_PAINT_MAX_CLIP_DEPTH * sizeof(hpgs_paint_clipper *));
ret->path = hpgs_new_paint_path();
if (!ret->path) goto fatal_error;
ret->path_clipper = hpgs_new_paint_clipper(bb,
image->height,
16,ret->overscan);
if (!ret->path_clipper) goto fatal_error;
ret->gstate = hpgs_new_gstate();
if (!ret->gstate) goto fatal_error;
// Initial dimesion of clip segments is 4.
ret->clippers[0] = hpgs_new_paint_clipper(bb,
image->height,4,ret->overscan);
if (!ret->clippers[0]) goto fatal_error;
if (hpgs_paint_clipper_reset(ret->clippers[0],bb->llx,bb->urx))
goto fatal_error;
ret->clip_depth = 1;
ret->current_clipper = 0;
ret->page_bb = *bb;
ret->xres = image->width/(bb->urx-bb->llx);
ret->yres = image->height/(bb->ury-bb->lly);
if (hpgs_image_set_resolution(image,72.0*ret->xres,72.0*ret->yres))
goto fatal_error;
ret->image_interpolation = 0;
ret->color.r = 0;
ret->color.g = 0;
ret->color.b = 0;
ret->color.index = 0;
ret->patcol.r = 0;
ret->patcol.g = 0;
ret->patcol.b = 0;
ret->inherited.vtable = &pdv_vtable;
}
return ret;
fatal_error:
if (ret->filename) free(ret->filename);
if (ret->path) hpgs_paint_path_destroy(ret->path);
if (ret->clippers[0]) hpgs_paint_clipper_destroy(ret->clippers[0]);
if (ret->gstate) hpgs_gstate_destroy(ret->gstate);
if (ret->image) hpgs_image_destroy(ret->image);
free(ret);
return 0;
}
/*! Sets the image interpolation value of the given paint device.
Currently, the following values are supported:
\li 0 no image iterpolation
\li 1 linear image interpolation.
Other values specifiying square or cubic interpolation may be
supported in the future. The default value is 0.
*/
void hpgs_paint_device_set_image_interpolation (hpgs_paint_device *pdv, int i)
{
pdv->image_interpolation = i;
}
/*! Sets the minimal alpha value for thin lines, when antialiasing is
in effect. The supplied value must be grater than or equal to 0.01 and
lesser than or equal to 10.0. Other values are ignored.
*/
void hpgs_paint_device_set_thin_alpha (hpgs_paint_device *pdv, double a)
{
if (a > 0.01 && a <= 10.0)
pdv->thin_alpha = a;
}
/*! Fills the intersection of the given path with the current clip
path of the paint device \c pdv using the current graphics state of \c pdv.
if \c winding is \c HPGS_TRUE, the non-zero winding rule is used for filling,
otherwise the exclusive-or rule applies.
Return values:
\li 0 Sucess.
\li -1 An error ocurred.
Call \c hpgs_device_get_error in order to retrieve the error message.
*/
int hpgs_paint_device_fill(hpgs_paint_device *pdv,
hpgs_paint_path *path,
hpgs_bool winding,
hpgs_bool stroke )
{
const hpgs_paint_clipper *clip = pdv->clippers[pdv->current_clipper];
if (hpgs_paint_clipper_cut(pdv->path_clipper,path))
return hpgs_set_error(hpgs_i18n("fill: Error cutting current path."));
if (hpgs_paint_clipper_emit(pdv->image,
pdv->path_clipper,clip,
&pdv->color,winding,stroke))
{
if (hpgs_have_error())
return hpgs_error_ctxt(hpgs_i18n("fill: Image error"));
return hpgs_set_error(hpgs_i18n("fill: Error emitting scanlines."));
}
hpgs_paint_clipper_clear(pdv->path_clipper);
return 0;
}
/*! Sets the intersection of the given path with the current clip
path of the paint device \c pdv as the current clip path of \c pdv.
if \c winding is \c HPGS_TRUE, the non-zero winding rule is used for the
path intersection, otherwise the exclusive-or rule applies.
Return values:
\li 0 Sucess.
\li -1 An error ocurred.
Call \c hpgs_device_get_error in order to retrieve the error message.
*/
int hpgs_paint_device_clip(hpgs_paint_device *pdv,
hpgs_paint_path *path,
hpgs_bool winding)
{
const hpgs_paint_clipper *clip = pdv->clippers[pdv->current_clipper];
if (hpgs_paint_clipper_cut(pdv->path_clipper,path))
return hpgs_set_error(hpgs_i18n("clip: Error cutting current path."));
hpgs_paint_clipper *nclip =
hpgs_paint_clipper_clip(pdv->path_clipper,clip,winding);
if (!nclip)
return hpgs_set_error(hpgs_i18n("clip: Out of memory creating new clipper."));
// push the new clipper onto the stack of clippers.
pdv->current_clipper = pdv->clip_depth-1;
if (pdv->clippers[pdv->current_clipper])
hpgs_paint_clipper_destroy(pdv->clippers[pdv->current_clipper]);
pdv->clippers[pdv->current_clipper] = nclip;
hpgs_paint_clipper_clear(pdv->path_clipper);
return 0;
}

View File

@ -0,0 +1,287 @@
/***********************************************************************
* *
* $Id: hpgspaint.h 270 2006-01-29 21:12:23Z softadm $
* *
* hpgs - HPGl Script, a hpgl/2 interpreter, which uses a Postscript *
* API for rendering a scene and thus renders to a variety of *
* devices and fileformats. *
* *
* (C) 2004-2006 ev-i Informationstechnologie GmbH http://www.ev-i.at *
* *
* Author: Wolfgang Glas *
* *
* hpgs is free software; you can redistribute it and/or *
* modify it under the terms of the GNU Lesser General Public *
* License as published by the Free Software Foundation; either *
* version 2.1 of the License, or (at your option) any later version. *
* *
* hpgs is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU *
* Lesser General Public License for more details. *
* *
* You should have received a copy of the GNU Lesser General Public *
* License along with this library; if not, write to the *
* Free Software Foundation, Inc., 59 Temple Place, Suite 330, *
* Boston, MA 02111-1307 USA *
* *
***********************************************************************
* *
* The declarations for the pixel painter. *
* *
***********************************************************************/
#ifndef __HPGS_PAINT_H
#define __HPGS_PAINT_H
#include<hpgs.h>
#ifdef __cplusplus
extern "C" {
#endif
/*! \file hpgspaint.h
\brief Internals of the pixel renderer.
A header file, which declares the structures and functions internally
used by \c hpgs_paint_device.
*/
typedef struct hpgs_scanline_point_st hpgs_scanline_point;
typedef struct hpgs_paint_scanline_st hpgs_paint_scanline;
typedef struct hpgs_paint_clipper_st hpgs_paint_clipper;
/*! @addtogroup paint_device
* @{
*/
#define HPGS_PAINT_MAX_CLIP_DEPTH 16
/*! \brief The pixel rendering vector graphics device.
This structure has a public alias \c hpgs_paint_device and
represents a \c hpgs_device which draws to a given \c hpgs_image.
It is capable of drawing polgonal data with optional antialiasing.
Image may be drawn using a linear interpolation of the pixel values
or uninterpolated.
The following figure outlines the coordinate setup of a paint device.
\image html clipper.png
\image latex clipper.eps "Coordinate setup of hpgs_paint_device"
Further details on antialiasing and scanline setup are described in the
documentation of \c hpgs_paint_clipper_st.
*/
struct hpgs_paint_device_st
{
hpgs_device inherited; /*!< The base device structure. */
hpgs_image *image; /*!< The image to which we draw. */
char *filename; /*!< The image filename without an eventual extension. */
hpgs_bbox page_bb;/*! The bounding box in world coordinates, which is mapped onto
the image. */
double xres; /*!< The resolution of the image in x direction. */
double yres; /*!< The resolution of the image in y direction. */
hpgs_bool overscan;
/*!< Specifies, whether we use antialiasing for rendering the image. */
double thin_alpha; /*!< The minimal alpha value for antialiased thin lines. */
hpgs_paint_path *path; /*!< The current path, which is under contruction. */
hpgs_paint_clipper *path_clipper; /*!< The mapping of the current path onto the defined scanlines. */
hpgs_paint_clipper *clippers[HPGS_PAINT_MAX_CLIP_DEPTH];
/*!< A stack of mappings of the clip path' of onto the defined scanlines. */
int current_clipper; /*!< The position of the current clip path in \c clippers. */
int clip_depth;
/*!< The current depth of the clip stack, i.e. the number of time
\c hpgs_clip or \c hpgs_eoclip has been called. */
hpgs_gstate *gstate; /*!< The graphics state. */
hpgs_paint_color color; /*!< The current color transformed to a device color. */
hpgs_palette_color patcol; /*!< The current pattern color transformed to a device color. */
int image_interpolation; /*!< A flag holding whether we do image interpolation. */
};
HPGS_INTERNAL_API int hpgs_paint_device_fill(hpgs_paint_device *pdv,
hpgs_paint_path *path,
hpgs_bool winding,
hpgs_bool stroke);
HPGS_INTERNAL_API int hpgs_paint_device_clip(hpgs_paint_device *pdv,
hpgs_paint_path *path,
hpgs_bool winding);
HPGS_INTERNAL_API int hpgs_paint_device_drawimage(hpgs_paint_device *pdv,
const hpgs_image *img,
const hpgs_point *ll, const hpgs_point *lr,
const hpgs_point *ur);
/*! @} */ /* end of group paint_device */
/*! @addtogroup path
* @{
*/
#define HPGS_BEZIER_NSEGS 16
typedef struct hpgs_bezier_length_st hpgs_bezier_length;
/*! \brief A structure for holding intermediate values for length
calculations of a bezier spline.
This structure has a public alias \c hpgs_bezier_length and holds
internals of a bezier spline used during length calculations.
*/
struct hpgs_bezier_length_st
{
double l[HPGS_BEZIER_NSEGS+1]; /*!< The length of the spline from the beginning to the parameter -0.5+i/HPGS_BEZIER_NSEGS. */
double dl[HPGS_BEZIER_NSEGS+1]; /*!< The derivative of the length of the spline at the parameter -0.5+i/HPGS_BEZIER_NSEGS. */
};
HPGS_INTERNAL_API void hpgs_bezier_length_init(hpgs_bezier_length *b,
const hpgs_paint_path *path, int i);
HPGS_INTERNAL_API double hpgs_bezier_length_param(const hpgs_bezier_length *b, double l);
/*! @} */ /* end of group path */
/*! @addtogroup scanline
* @{
*/
/*! \brief An intersection point of a path with a scanline.
This structure has a public alias \c hpgs_scanline_point and holds
the information of an intersection point of a path with a scanline.
*/
struct hpgs_scanline_point_st
{
double x;
/*!< The x coordinate of the intersection point of the path with the scanline. */
int order;
/*!< The order of the intersection.
An \c order of 1 means an upward intersection, -1 means a downward intersection.
Horizontal intersection are stored as two distinct intersection points with the same
x coordinate. If antialiasing is used, the order represents a delta of a broken down
winding value. A order of 256 means that the scanline is intersected from the bottom
to the top of a physical image row between the previous and the actual intersection
point. if The order is smaller than 256, the physical row is not touched in its whole
extend an a corresponding alpha value less than 1 is generated. */
};
/*! \brief A scanline of the pixel renderer.
This structure has a public alias \c hpgs_paint_scanline and holds
the intersections points of a path with a scanline.
*/
struct hpgs_paint_scanline_st
{
/*@{*/
/*! A vector of intersection points.
*/
hpgs_scanline_point *points;
int points_malloc_size;
int n_points;
/*@}*/
};
/*! \brief A collection of scanlines for mapping paths onto images.
This structure has a public alias \c hpgs_paint_clipper and holds
intersection points of a path with a rectangular region represented
by a series of equidistantly distributed scanlines.
The \c overscan member determines, whether we use antialiasing for
mappinng the path. The name of this structure member is historical,
because up to \c hpgs-0.8.x the antialiasing renderer effectively used
more than one scanline per physical image row in order to caclulate
alpha values.
Nowadays a scanline always represents the middle of the
corresponding physical row of the image as sketch in the folowing figure,
which show the generated segment for non-antialiased rendering.
\image html scanline_0.png
\image latex scanline_0.eps "scanline setup and pixel filling without antialiasing."
If \c overscan is non-zero, the segment generator caclulates slopes of the
trapezoids, which are generated by the path segments cutting the boundaries
between two physical grid lines as sketched in the following figure.
\image html scanline_n.png
\image latex scanline_n.eps "scanline setup and alpha generation with antialiasing."
*/
struct hpgs_paint_clipper_st
{
/*@{ */
/*! The vector of scanlines in this clipper.
*/
hpgs_paint_scanline *scanlines;
int n_scanlines;
/*@} */
hpgs_bbox bb; /*! The bounding box of this clipper in world coordinates. */
/*@{ */
/*! The mapping of scanline numbers to world coordinates.
\c iscan=(y0-y)/yfac and \c y=y0-iscan*yfac.
*/
double yfac; // height of a single scanline.
double y0; // y for scanline 0
/*@} */
hpgs_bool overscan; /*!< Do we use antialiasing ?. */
int height; /*!< Number of physical pixels of the underlying image. */
int iscan0; /*!< The first scanline with non-zero intersections. */
int iscan1; /*!< The last scanline with non-zero intersections. */
};
HPGS_INTERNAL_API hpgs_paint_clipper *hpgs_new_paint_clipper(const hpgs_bbox *bb,
int height,
int scanline_msize,
int overscan);
HPGS_INTERNAL_API hpgs_paint_clipper *hpgs_paint_clipper_clip(const hpgs_paint_clipper *orig,
const hpgs_paint_clipper *clip,
hpgs_bool winding);
HPGS_INTERNAL_API int hpgs_paint_clipper_cut(hpgs_paint_clipper *c,
hpgs_paint_path *path);
HPGS_INTERNAL_API int hpgs_paint_clipper_thin_cut(hpgs_paint_clipper *c,
hpgs_paint_path *path,
const hpgs_gstate *gstate);
HPGS_INTERNAL_API int hpgs_paint_clipper_emit (hpgs_image *image,
const hpgs_paint_clipper *img,
const hpgs_paint_clipper *clip,
const hpgs_paint_color *c,
hpgs_bool winding,
hpgs_bool stroke);
HPGS_INTERNAL_API int hpgs_paint_clipper_reset(hpgs_paint_clipper *c, double llx, double urx);
HPGS_INTERNAL_API void hpgs_paint_clipper_clear(hpgs_paint_clipper *c);
HPGS_INTERNAL_API void hpgs_paint_clipper_destroy(hpgs_paint_clipper *c);
/*! @} */ /* end of group scanline */
#ifdef __cplusplus
} // end of extern "C"
#endif
#endif /* ! __HPGS_PAINT_H */

View File

@ -0,0 +1,469 @@
/***********************************************************************
* *
* $Id: hpgspaintimage.c 281 2006-02-25 19:40:31Z softadm $
* *
* hpgs - HPGl Script, a hpgl/2 interpreter, which uses a Postscript *
* API for rendering a scene and thus renders to a variety of *
* devices and fileformats. *
* *
* (C) 2004-2006 ev-i Informationstechnologie GmbH http://www.ev-i.at *
* *
* Author: Wolfgang Glas *
* *
* hpgs is free software; you can redistribute it and/or *
* modify it under the terms of the GNU Lesser General Public *
* License as published by the Free Software Foundation; either *
* version 2.1 of the License, or (at your option) any later version. *
* *
* hpgs is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU *
* Lesser General Public License for more details. *
* *
* You should have received a copy of the GNU Lesser General Public *
* License along with this library; if not, write to the *
* Free Software Foundation, Inc., 59 Temple Place, Suite 330, *
* Boston, MA 02111-1307 USA *
* *
***********************************************************************
* *
* The implementation of the public API for the pixel painter. *
* *
***********************************************************************/
#include<hpgspaint.h>
#include<math.h>
#include<assert.h>
#include<string.h>
//#define HPGS_PAINT_IMAGE_DEBUG
#ifdef HPGS_PAINT_IMAGE_DEBUG
static void log_mat_6(const char *lead, const double *mat)
{
hpgs_log("%s%10lg,%10lg,%10lg\n%*s%10lg,%10lg,%10lg.\n",
lead,mat->dx,mat->mxx,mat->mxy,
strlen(lead)," ",mat->dy,mat->myx,mat->myy);
}
#endif
// multiplicates the given vector with the specified matrix.
// This is here in order to allow efficient inlining of the code.
//
static void mat_6_mul(hpgs_point *pout, const hpgs_matrix *mat, double xin, double yin)
{
pout->x = mat->dx + mat->mxx * xin + mat->mxy * yin;
pout->y = mat->dy + mat->myx * xin + mat->myy * yin;
}
// build matrix from destination to source pixel coordinates.
static void build_inv_matrix(hpgs_matrix *m,
const hpgs_paint_clipper *c,
const hpgs_image *dest,
const hpgs_image *src,
const hpgs_point *ll,
const hpgs_point *ul,
const hpgs_point *lr,
const hpgs_point *ur)
{
// image to device coordinates.
hpgs_matrix a = { ul->x, ul->y,
(lr->x-ll->x)/src->width, (lr->x-ur->x)/src->height,
(lr->y-ll->y)/src->width, (lr->y-ur->y)/src->height };
// device to target raster coordinates.
hpgs_matrix b = {-0.5-c->bb.llx*dest->width/(c->bb.urx-c->bb.llx), c->y0/c->yfac,
dest->width/(c->bb.urx-c->bb.llx), 0.0,
0.0, -1.0/c->yfac };
hpgs_matrix tmp;
// take half a pixel into account.
a.dx += 0.5 * (a.mxx + a.mxy);
a.dy += 0.5 * (a.myx + a.myy);
hpgs_matrix_concat(&tmp,&b,&a);
#ifdef HPGS_PAINT_IMAGE_DEBUG
log_mat_6("a = ",a);
log_mat_6("b = ",b);
log_mat_6("b*a = ",tmp);
#endif
hpgs_matrix_invert(m,&tmp);
}
typedef int (*put_point_func_t)(hpgs_image *, const hpgs_image *,
int, int, const hpgs_point *, double);
static int put_point_0(hpgs_image *dest, const hpgs_image *src,
int dest_i, int dest_j, const hpgs_point *src_point,
double alpha)
{
hpgs_paint_color col;
double a;
int src_i = (int)rint(src_point->x);
int src_j = (int)rint(src_point->y);
if (src_i < 0 || src_i >= src->width) return 0;
if (src_j < 0 || src_j >= src->height) return 0;
hpgs_image_get_pixel(src,src_i,src_j,&col,&a);
if (hpgs_image_define_color (dest,&col))
return -1;
return hpgs_image_rop3_pixel(dest,dest_i,dest_j,&col,
alpha*a);
}
static int put_point_1(hpgs_image *dest, const hpgs_image *src,
int dest_i, int dest_j, const hpgs_point *src_point,
double alpha)
{
hpgs_paint_color col;
double aa,a=0.0;
double r=0.0,g=0.0,b=0.0;
double w;
double sw = 0.0;
int src_i = (int)ceil(src_point->x);
int src_j = (int)ceil(src_point->y);
double wx = ceil(src_point->x) - src_point->x;
double wy = ceil(src_point->y) - src_point->y;
if (src_i < 0 || src_i > src->width) return 0;
if (src_j < 0 || src_j > src->height) return 0;
if (src_i > 0)
{
if (src_j > 0)
{
hpgs_image_get_pixel(src,src_i-1,src_j-1,&col,&aa);
w = wx+wy;
r+=w*col.r;
g+=w*col.g;
b+=w*col.b;
a += w*aa;
sw += w;
}
if (src_j < src->height)
{
hpgs_image_get_pixel(src,src_i-1,src_j,&col,&aa);
w = 1.0-wy+wx;
r+=w*col.r;
g+=w*col.g;
b+=w*col.b;
a += w*aa;
sw += w;
}
}
if (src_i < src->width)
{
if (src_j > 0)
{
hpgs_image_get_pixel(src,src_i,src_j-1,&col,&aa);
w = 1.0-wx+wy;
r+=w*col.r;
g+=w*col.g;
b+=w*col.b;
a += w*aa;
sw += w;
}
if (src_j < src->height)
{
hpgs_image_get_pixel(src,src_i,src_j,&col,&aa);
w=2.0-wx-wy;
r+=w*col.r;
g+=w*col.g;
b+=w*col.b;
a += w*aa;
sw += w;
}
}
if (!sw) return 0;
col.r = r / sw;
col.g = g / sw;
col.b = b / sw;
if (hpgs_image_define_color (dest,&col))
return -1;
return hpgs_image_rop3_pixel(dest,dest_i,dest_j,&col,
0.25*alpha*a);
}
/*!
Draws the intersection of the given image with the current clip
path of the paint device \c pdv to the destination image of \c pdv.
The arguments \c ll, \c lr and \c ur are the
lower left, lower right and upper right corner of the drawn image
in world coordinates.
Return values:
\li 0 Sucess.
\li -1 An error ocurred.
Call \c hpgs_device_get_error in order to retrieve the error message.
*/
int hpgs_paint_device_drawimage(hpgs_paint_device *pdv,
const hpgs_image *img,
const hpgs_point *ll, const hpgs_point *lr,
const hpgs_point *ur)
{
const hpgs_paint_clipper *c = pdv->clippers[pdv->current_clipper];
put_point_func_t put_point_func = put_point_0;
hpgs_point ul;
double ll_i,lr_i,ur_i,ul_i;
int iscan0;
int iscan1;
int iscan;
hpgs_matrix imat[6];
if (pdv->image_interpolation)
put_point_func = put_point_1;
ul.x = ll->x + (ur->x - lr->x);
ul.y = ll->y + (ur->y - lr->y);
build_inv_matrix(imat,c,pdv->image,img,ll,&ul,lr,ur);
ll_i = (c->y0 - ll->y)/c->yfac;
lr_i = (c->y0 - lr->y)/c->yfac;
ur_i = (c->y0 - ur->y)/c->yfac;
ul_i = (c->y0 - ul.y)/c->yfac;
iscan0 = (int)ceil(ll_i);
if (lr_i < iscan0) iscan0 = (int)ceil(lr_i);
if (ur_i < iscan0) iscan0 = (int)ceil(ur_i);
if (ul_i < iscan0) iscan0 = (int)ceil(ul_i);
if (iscan0 < c->iscan0) iscan0 = c->iscan0;
iscan1 = (int)floor(ll_i);
if (lr_i > iscan1) iscan1 = (int)floor(lr_i);
if (ur_i > iscan1) iscan1 = (int)floor(ur_i);
if (ul_i > iscan1) iscan1 = (int)floor(ul_i);
if (iscan1 > c->iscan1) iscan1 = c->iscan1;
#ifdef HPGS_PAINT_IMAGE_DEBUG
hpgs_log("ll_i,lr_i,ur_i,ul_i,iscan0,iscan1=%lg,%lg,%lg,%lg,%d,%d.\n",
ll_i,lr_i,ur_i,ul_i,iscan0,iscan1);
print_mat_6(stderr,"imat = ",imat);
#endif
for (iscan = iscan0; iscan <= iscan1; ++iscan)
{
double x[2];
int ix = 0;
int io;
const hpgs_paint_scanline *scanline = c->scanlines+iscan;
if ((iscan > ll_i && iscan < lr_i) ||
(iscan < ll_i && iscan > lr_i) )
{
x[ix] = ((ll_i - iscan)*lr->x + (iscan - lr_i)*ll->x) / (ll_i-lr_i);
++ix;
}
if ((iscan > lr_i && iscan < ur_i) ||
(iscan < lr_i && iscan > ur_i) )
{
x[ix] = ((lr_i - iscan)*ur->x + (iscan - ur_i)*lr->x) / (lr_i-ur_i);
++ix;
}
if ((iscan > ur_i && iscan < ul_i) ||
(iscan < ur_i && iscan > ul_i) )
{
x[ix] = ((ur_i - iscan)*ul.x + (iscan - ul_i)*ur->x) / (ur_i-ul_i);
++ix;
}
if ((iscan > ul_i && iscan < ll_i) ||
(iscan < ul_i && iscan > ll_i) )
{
x[ix] = ((ul_i - iscan)*ll->x + (iscan - ll_i)*ul.x) / (ul_i-ll_i);
++ix;
}
if (ix!=2) continue;
if (x[0] > x[1])
{
double tmp = x[0];
x[0] = x[1];
x[1] = tmp;
}
if (pdv->overscan)
{
int out_state = 0;
io = 0;
// go through clip segments antialiased
while (io<scanline->n_points)
{
double xleft,xright,ixleft,ixright;
double ileft,iright,ii,alpha_left,alpha_right;
hpgs_point src_point;
xleft= scanline->points[io].x;
while (io<scanline->n_points && scanline->points[io].x == xleft)
{
out_state += scanline->points[io].order;
++io;
}
if (io >= scanline->n_points) break;
alpha_left = out_state/256.0;
xright = scanline->points[io].x;
alpha_right = (out_state+scanline->points[io].order)/256.0;
ixright = xright;
ixleft = xleft;
if (ixleft < x[0]) ixleft = x[0];
if (ixleft > x[1]) ixleft = x[1];
if (ixright < x[0]) ixright = x[0];
if (ixright > x[1]) ixright = x[1];
if ((alpha_left == 0.0 && alpha_right == 0.0) ||
ixleft >= ixright) continue;
ixleft = pdv->image->width*(ixleft-c->bb.llx) / (c->bb.urx-c->bb.llx);
ixright = pdv->image->width*(ixright-c->bb.llx) / (c->bb.urx-c->bb.llx);
ileft = ceil(ixleft);
iright = floor(ixright);
// output left corner points with alpha
if (ileft >= 1.0)
{
double alpha = (ileft - ixleft) *
(alpha_left*(xright-0.5*(ileft+xleft))+alpha_right*(0.5*(ileft+xleft)-xleft))/(xright-xleft);
mat_6_mul(&src_point,imat,ileft-1.0,iscan);
if (put_point_func(pdv->image,img,ileft-1.0,iscan,&src_point,alpha))
return -1;
#ifdef HPGS_PAINT_IMAGE_DEBUG
hpgs_log("src: %lg,%lg, dest: %lg,%d.\n",
src_point->x,src_point->y,ileft-1.0,iscan);
#endif
}
// output intermediate pixels.
for (ii = ileft; ii < iright; ++ii)
{
double alpha = (alpha_left*(xright-(ii+0.5))+alpha_right*((ii+0.5)-xleft))/(xright-xleft);
mat_6_mul(&src_point,imat,ii,iscan);
if (put_point_func(pdv->image,img,ii,iscan,&src_point,alpha))
return -1;
}
// output right corner points with alpha
if (iright >= ileft && iright < pdv->image->width)
{
double alpha = (ixright - iright) *
(alpha_left*(xright-0.5*(iright+xright))+alpha_right*(0.5*(iright+xright)-xleft))/(xright-xleft);
mat_6_mul(&src_point,imat,iright,iscan);
if (put_point_func(pdv->image,img,iright,iscan,&src_point,alpha))
return -1;
#ifdef HPGS_PAINT_IMAGE_DEBUG
hpgs_log("src: %lg,%lg, dest: %lg,%d.\n",
src_point->x,src_point->y,iright,iscan);
#endif
}
}
}
else
{
// go through clip segments - non-antialiased
for (io = 0; io+1<scanline->n_points; io+=2)
{
double xleft= scanline->points[io].x;
double xright= scanline->points[io+1].x;
double ileft,iright,ii;
hpgs_point src_point;
if (xleft < x[0]) xleft = x[0];
if (xleft > x[1]) xleft = x[1];
if (xright < x[0]) xright = x[0];
if (xright > x[1]) xright = x[1];
if (xleft >= xright) continue;
xleft = pdv->image->width*(xleft-c->bb.llx) / (c->bb.urx-c->bb.llx);
xright = pdv->image->width*(xright-c->bb.llx) / (c->bb.urx-c->bb.llx);
ileft = ceil(xleft);
iright = floor(xright);
// output left corner points with alpha
if (ileft >= 1.0)
{
double alpha = ileft - xleft;
mat_6_mul(&src_point,imat,ileft-1.0,iscan);
if (put_point_func(pdv->image,img,ileft-1.0,iscan,&src_point,alpha))
return -1;
#ifdef HPGS_PAINT_IMAGE_DEBUG
hpgs_log("src: %lg,%lg, dest: %lg,%d.\n",
src_point->x,src_point->y,ileft-1.0,iscan);
#endif
}
// output intermediate pixels.
for (ii = ileft; ii < iright; ++ii)
{
mat_6_mul(&src_point,imat,ii,iscan);
if (put_point_func(pdv->image,img,ii,iscan,&src_point,1.0))
return -1;
}
// output right corner points with alpha
if (iright >= ileft && iright < pdv->image->width)
{
double alpha = xright - iright;
mat_6_mul(&src_point,imat,iright,iscan);
if (put_point_func(pdv->image,img,iright,iscan,&src_point,alpha))
return -1;
#ifdef HPGS_PAINT_IMAGE_DEBUG
hpgs_log("src: %lg,%lg, dest: %lg,%d.\n",
src_point->x,src_point->y,iright,iscan);
#endif
}
}
}
}
return 0;
}

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,290 @@
/***********************************************************************
* *
* $Id: hpgspe.c 347 2006-09-21 09:36:01Z softadm $
* *
* hpgs - HPGl Script, a hpgl/2 interpreter, which uses a Postscript *
* API for rendering a scene and thus renders to a variety of *
* devices and fileformats. *
* *
* (C) 2004-2006 ev-i Informationstechnologie GmbH http://www.ev-i.at *
* *
* Author: Wolfgang Glas *
* *
* hpgs is free software; you can redistribute it and/or *
* modify it under the terms of the GNU Lesser General Public *
* License as published by the Free Software Foundation; either *
* version 2.1 of the License, or (at your option) any later version. *
* *
* hpgs is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU *
* Lesser General Public License for more details. *
* *
* You should have received a copy of the GNU Lesser General Public *
* License along with this library; if not, write to the *
* Free Software Foundation, Inc., 59 Temple Place, Suite 330, *
* Boston, MA 02111-1307 USA *
* *
***********************************************************************
* *
* The implementation of the HPGL reader. *
* *
***********************************************************************/
#include <hpgsreader.h>
#include <math.h>
#include <string.h>
#include <ctype.h>
//#define HPGS_DEBUG_PE
/*
HPGL command PE (Polyline Encoded)
*/
static int base32_decode (hpgs_reader *reader, unsigned *value)
{
int digit;
int i=0;
*value=0;
while (i<7)
{
if (reader->last_byte == EOF) return -1;
reader->last_byte &= 0x7f;
if (reader->last_byte > 94)
digit = reader->last_byte - 95;
else
digit = reader->last_byte - 63;
if (digit >= 0 && digit <= 31)
{
*value |= digit << (5*i);
if (reader->last_byte > 94) return 0;
++i;
}
else
// ignore all escape characters, including space.
if (reader->last_byte > 32) return -1;
reader->last_byte = hpgs_getc(reader->in);
}
return -1;
}
static int base64_decode (hpgs_reader *reader, unsigned *value)
{
int digit;
int i=0;
*value=0;
while (i<6)
{
if (reader->last_byte == EOF) return -1;
if (reader->last_byte > 190)
digit = reader->last_byte - 191;
else
digit = reader->last_byte - 63;
if (digit >= 0 && digit <= 63)
{
*value |= digit << (6*i);
if (reader->last_byte > 190) return 0;
++i;
}
else
// ignore all escape characters, including space.
if (reader->last_byte > 32) return -1;
reader->last_byte = hpgs_getc(reader->in);
}
return -1;
}
static int int_decode (hpgs_reader *reader, int *value, int b32)
{
unsigned uval;
if (b32)
{ if (base32_decode(reader,&uval)) return -1; }
else
{ if (base64_decode(reader,&uval)) return -1; }
if (uval & 1)
*value = - (uval >> 1);
else
*value = uval >> 1;
return 0;
}
static int double_decode (hpgs_reader *reader, double *value,
double fract_fac, int b32)
{
int int_val;
if (int_decode(reader,&int_val,b32))
return -1;
*value = int_val * fract_fac;
return 0;
}
static int coord_decode (hpgs_reader *reader, hpgs_point *p,
double fract_fac, int b32, int rel)
{
if (double_decode (reader,&p->x,fract_fac,b32)) return -1;
reader->last_byte = hpgs_getc(reader->in);
if (double_decode (reader,&p->y,fract_fac,b32)) return -1;
if (rel)
{
hpgs_matrix_scale (p,&reader->total_matrix,p);
p->x+=reader->current_point.x;
p->y+=reader->current_point.y;
}
else
{
hpgs_matrix_xform (p,&reader->total_matrix,p);
}
return 0;
}
int hpgs_reader_do_PE(hpgs_reader *reader)
{
hpgs_point p0;
hpgs_point p;
double fract_fac = 1.0;
int rel = 1;
int b32 = 0;
int rect = 0;
reader->pen_down = 1;
#ifdef HPGS_DEBUG_PE
hpgs_log("PE start ***************\n");
#endif
while (1)
{
reader->last_byte = hpgs_getc(reader->in);
if (reader->last_byte == EOF || reader->last_byte == ';')
{
reader->eoc = 1;
reader->bytes_ignored = 0;
return 0;
}
switch (reader->last_byte & 0x7f)
{
case '7':
b32 = 1;
break;
case '9':
rect = 1;
reader->pen_down = 0;
break;
case ':':
{
int pen;
reader->last_byte = hpgs_getc(reader->in);
if (int_decode(reader,&pen,b32)) return -1;
if (hpgs_reader_do_setpen(reader,pen)) return -1;
}
break;
case '>':
{
int fract_bits;
reader->last_byte = hpgs_getc(reader->in);
if (int_decode(reader,&fract_bits,b32)) return -1;
fract_fac = 1.0;
while (--fract_bits >= 0)
fract_fac *= 0.5;
}
break;
case '<':
reader->pen_down = 0;
rect = 0;
break;
case '=':
rel = 0;
break;
default:
if (isspace(reader->last_byte)) break;
if (coord_decode(reader,&p,fract_fac,b32,rel))
{
// Well, some HPGL drivers are so broken, that they
// can't write decent PE vommands.
// So let's hand over control to the recovery code in
// hpgs_read().
//
if (reader->last_byte != EOF)
{
reader->eoc = 1;
reader->bytes_ignored = 1;
return 0;
}
return -1;
}
#ifdef HPGS_DEBUG_PE
hpgs_log("p,down,rect = (%lg,%lg),%d,%d.\n",p.x,p.y,reader->pen_down,rect);
#endif
switch (rect)
{
case 1:
if (hpgs_reader_checkpath(reader)) return -1;
p0 = p;
if (hpgs_reader_moveto(reader,&p0)) return -1;
rect = 2;
break;
case 2:
{
hpgs_point pp;
pp.x=p.x;
pp.y=p0.y;
if (hpgs_reader_lineto(reader,&pp)) return -1;
if (hpgs_reader_lineto(reader,&p))
return -1;
pp.x=p0.x;
pp.y=p.y;
if (hpgs_reader_lineto(reader,&pp)) return -1;
if (hpgs_reader_lineto(reader,&p0)) return -1;
// only do a fill, if we are not in polygon mode.
if (!reader->polygon_mode &&
hpgs_reader_fill(reader,1)) return -1;
}
reader->pen_down = 1;
rect = 1;
break;
default:
if (reader->pen_down)
{
if (hpgs_reader_lineto(reader,&p)) return -1;
}
else
{
if (hpgs_reader_checkpath(reader)) return -1;
if (hpgs_reader_moveto(reader,&p)) return -1;
}
reader->pen_down = 1;
}
rel = 1;
}
}
}

View File

@ -0,0 +1,421 @@
/***********************************************************************
* *
* $Id: hpgspen.c 298 2006-03-05 18:18:03Z softadm $
* *
* hpgs - HPGl Script, a hpgl/2 interpreter, which uses a Postscript *
* API for rendering a scene and thus renders to a variety of *
* devices and fileformats. *
* *
* (C) 2004-2006 ev-i Informationstechnologie GmbH http://www.ev-i.at *
* *
* Author: Wolfgang Glas *
* *
* hpgs is free software; you can redistribute it and/or *
* modify it under the terms of the GNU Lesser General Public *
* License as published by the Free Software Foundation; either *
* version 2.1 of the License, or (at your option) any later version. *
* *
* hpgs is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU *
* Lesser General Public License for more details. *
* *
* You should have received a copy of the GNU Lesser General Public *
* License along with this library; if not, write to the *
* Free Software Foundation, Inc., 59 Temple Place, Suite 330, *
* Boston, MA 02111-1307 USA *
* *
***********************************************************************
* *
* The implementation of the HPGL reader. *
* *
***********************************************************************/
#include <hpgsreader.h>
#include <math.h>
#include <string.h>
#include <ctype.h>
/*
Internal
*/
static int hpgs_reader_set_number_of_pens(hpgs_reader *reader, int npens)
{
double *pw =(double *)realloc(reader->pen_widths,npens*sizeof(double));
if (!pw)
return hpgs_set_error(hpgs_i18n("Out of memory growing pen width array."));
reader->pen_widths = pw;
hpgs_color *pc = (hpgs_color *)realloc(reader->pen_colors,npens*sizeof(hpgs_color));
if (!pc)
return hpgs_set_error(hpgs_i18n("Out of memory growing pen color array."));
reader->pen_colors = pc;
for (;reader->npens<npens;++reader->npens)
{
reader->pen_widths[reader->npens] = 1.0;
reader->pen_colors[reader->npens].r = 0.0;
reader->pen_colors[reader->npens].g = 0.0;
reader->pen_colors[reader->npens].b = 0.0;
}
return 0;
}
/*
Do the pen select.
*/
int hpgs_reader_do_setpen(hpgs_reader *reader, int pen)
{
double width;
if (hpgs_reader_checkpath(reader)) return -1;
if (pen < 0)
return hpgs_set_error(hpgs_i18n("Illegal pen numer %d."),pen);
if (pen >= reader->npens)
{
if (pen < 256)
{
if (hpgs_reader_set_number_of_pens(reader,pen+1))
return -1;
}
else
{
if (reader->verbosity)
hpgs_log(hpgs_i18n("Illegal pen number %d replaced by %d.\n"),
pen, pen % reader->npens);
pen = pen % reader->npens;
}
}
reader->current_pen = pen;
width = reader->pen_widths[pen];
if (reader->pen_width_relative)
width *= hypot(reader->P2.x-reader->P1.x,
reader->P2.y-reader->P1.y ) * 0.001 * HP_TO_PT;
else
width *= HP_TO_PT / reader->world_scale;
width *= reader->page_scale;
if (hpgs_setlinewidth(reader->device,width*reader->lw_factor))
return -1;
return hpgs_setrgbcolor(reader->device,
&reader->pen_colors[pen]);
}
/*
HPGL command NP (Number of Pens)
*/
int hpgs_reader_do_NP (hpgs_reader *reader)
{
int npens=8;
if (!reader->eoc &&
hpgs_reader_read_int(reader,&npens)) return -1;
if (npens <= reader->npens) return 0;
return hpgs_reader_set_number_of_pens(reader,npens);
}
/*
HPGL command SP (Set Pen)
*/
int hpgs_reader_do_SP (hpgs_reader *reader)
{
int pen=0;
if (!reader->eoc &&
hpgs_reader_read_int(reader,&pen)) return -1;
return hpgs_reader_do_setpen(reader,pen);
}
/*
HPGL command PC (Pen Color)
*/
int hpgs_reader_do_PC (hpgs_reader *reader)
{
int pen=-1;
double r=-1.0e20,g=-1.0e20,b=-1.0e20;
if (!reader->eoc && hpgs_reader_read_int(reader,&pen)) return -1;
if (!reader->eoc && hpgs_reader_read_double(reader,&r)) return -1;
if (!reader->eoc && hpgs_reader_read_double(reader,&g)) return -1;
if (!reader->eoc && hpgs_reader_read_double(reader,&b)) return -1;
if (pen >= reader->npens)
{
if (pen < 256)
{
if (hpgs_reader_set_number_of_pens(reader,pen+1))
return -1;
}
else
{
if (reader->verbosity)
hpgs_log(hpgs_i18n("PC: Illegal pen number %d.\n"),pen);
return 0;
}
}
if (pen < 0)
{
hpgs_reader_set_std_pen_colors(reader,0,reader->npens);
pen = reader->current_pen;
}
else
{
if (r==-1.0e20 || g==-1.0e20 || b==-1.0e20)
{
hpgs_reader_set_std_pen_colors(reader,pen,1);
}
else
{
reader->pen_colors[pen].r =
(r - reader->min_color.r) / (reader->max_color.r - reader->min_color.r);
if (reader->pen_colors[pen].r < 0.0) reader->pen_colors[pen].r = 0.0;
if (reader->pen_colors[pen].r > 1.0) reader->pen_colors[pen].r = 1.0;
reader->pen_colors[pen].g =
(g - reader->min_color.g) / (reader->max_color.g - reader->min_color.g);
if (reader->pen_colors[pen].g < 0.0) reader->pen_colors[pen].g = 0.0;
if (reader->pen_colors[pen].g > 1.0) reader->pen_colors[pen].g = 1.0;
reader->pen_colors[pen].b =
(b - reader->min_color.b) / (reader->max_color.b - reader->min_color.b);
if (reader->pen_colors[pen].b < 0.0) reader->pen_colors[pen].b = 0.0;
if (reader->pen_colors[pen].b > 1.0) reader->pen_colors[pen].b = 1.0;
}
}
if (pen == reader->current_pen)
if (hpgs_setrgbcolor(reader->device,
&reader->pen_colors[pen]))
return -1;
return 0;
}
/*
HPGL command CR (Color Range)
*/
int hpgs_reader_do_CR (hpgs_reader *reader)
{
reader->min_color.r = 0.0;
reader->min_color.g = 0.0;
reader->min_color.b = 0.0;
reader->max_color.r = 255.0;
reader->max_color.g = 255.0;
reader->max_color.b = 255.0;
if (!reader->eoc)
{
if (hpgs_reader_read_double(reader,&reader->min_color.r)) return -1;
if (reader->eoc) return -1;
if (hpgs_reader_read_double(reader,&reader->max_color.r)) return -1;
if (reader->eoc) return -1;
if (hpgs_reader_read_double(reader,&reader->min_color.g)) return -1;
if (reader->eoc) return -1;
if (hpgs_reader_read_double(reader,&reader->max_color.g)) return -1;
if (reader->eoc) return -1;
if (hpgs_reader_read_double(reader,&reader->min_color.b)) return -1;
if (reader->eoc) return -1;
if (hpgs_reader_read_double(reader,&reader->max_color.b)) return -1;
}
return 0;
}
/*
HPGL command LA (Line Attributes)
*/
int hpgs_reader_do_LA(hpgs_reader *reader)
{
int kind;
int ivalue;
double rvalue;
static hpgs_line_cap caps[5] =
{ hpgs_cap_butt,
hpgs_cap_butt,
hpgs_cap_square,
hpgs_cap_round,
hpgs_cap_round };
static hpgs_line_join joins[7] =
{ hpgs_join_miter,
hpgs_join_miter,
hpgs_join_miter,
hpgs_join_miter,
hpgs_join_round,
hpgs_join_bevel,
hpgs_join_miter };
while (!reader->eoc)
{
if (hpgs_reader_read_int(reader,&kind)) return -1;
if (reader->eoc) return -1;
switch (kind)
{
case 3:
if (hpgs_reader_read_double(reader,&rvalue)) return -1;
if (hpgs_setmiterlimit(reader->device,rvalue)) return -1;
break;
case 1:
if (hpgs_reader_read_int(reader,&ivalue)) return -1;
if (ivalue >= 0 && ivalue < 5 &&
hpgs_setlinecap(reader->device,caps[ivalue])) return -1;
break;
case 2:
if (hpgs_reader_read_int(reader,&ivalue)) return -1;
if (ivalue >= 0 && ivalue < 7 &&
hpgs_setlinejoin(reader->device,joins[ivalue])) return -1;
break;
default:
return -1;
}
}
return 0;
}
/*
HPGL command LT (Line Type)
*/
int hpgs_reader_do_LT(hpgs_reader *reader)
{
float dashes[20];
int i,ndash;
int linetype=0;
double patlen = 4.0;
int mode = 0;
if (hpgs_reader_checkpath(reader)) return -1;
if (!reader->eoc &&
hpgs_reader_read_int(reader,&linetype)) return -1;
if (!reader->eoc &&
hpgs_reader_read_double(reader,&patlen)) return -1;
if (!reader->eoc &&
hpgs_reader_read_int(reader,&mode)) return -1;
if (linetype < -8 || linetype > 8)
{
if (reader->verbosity)
hpgs_log(hpgs_i18n("LT: Illegal linetype %d.\n"),linetype);
return 0;
}
// line type are store as percentages.
patlen *= 0.01;
if (mode)
patlen *= MM_TO_PT;
else
patlen *= hypot(reader->P2.x-reader->P1.x,
reader->P2.y-reader->P1.y ) * 0.01 * HP_TO_PT;
ndash = reader->linetype_nsegs[linetype+8];
if (ndash > 20) ndash = 20;
for (i=0;i<ndash;++i)
dashes[i] = reader->linetype_segs[linetype+8][i] * patlen;
return hpgs_setdash(reader->device,
dashes,ndash,0.0);
}
/*
HPGL command PW (Pen Width)
*/
int hpgs_reader_do_PW (hpgs_reader *reader)
{
int pen=-1;
double width=1.0;
if (!reader->eoc)
if (hpgs_reader_read_double(reader,&width)) return -1;
if (!reader->eoc)
{
if (hpgs_reader_read_int(reader,&pen)) return -1;
if (pen < 0 || pen >= reader->npens)
{
if (pen >= reader->npens && pen < 256)
{
if (hpgs_reader_set_number_of_pens(reader,pen+1))
return -1;
}
else
{
if (reader->verbosity)
hpgs_log(hpgs_i18n("PW: Illegal pen number %d.\n"),pen);
return 0;
}
}
}
if (reader->verbosity >= 2)
hpgs_log("PW: pen,width,rel = %d,%g,%d.\n",pen,width,reader->pen_width_relative);
if (reader->pen_width_relative)
width *= 10.0;
else
width *= MM_TO_PT;
if (pen < 0)
{
int i;
for (i=0;i<reader->npens;++i)
reader->pen_widths[i] = width;
}
else
reader->pen_widths[pen] = width;
if (pen < 0 || pen == reader->current_pen)
{
if (hpgs_reader_checkpath(reader)) return -1;
if (reader->pen_width_relative)
width *= hypot(reader->P2.x-reader->P1.x,
reader->P2.y-reader->P1.y ) * 0.001 * HP_TO_PT;
else
width *= HP_TO_PT / reader->world_scale;
width *= reader->page_scale;
if (hpgs_setlinewidth(reader->device,width*reader->lw_factor))
return -1;
}
return 0;
}
/*
HPGL command WU (Width Unit selection)
*/
int hpgs_reader_do_WU (hpgs_reader *reader)
{
reader->pen_width_relative=0;
if (!reader->eoc &&
hpgs_reader_read_int(reader,&reader->pen_width_relative)) return -1;
return 0;
}

View File

@ -0,0 +1,261 @@
/***********************************************************************
* *
* $Id: hpgspjl.c 384 2007-03-18 18:31:15Z softadm $
* *
* hpgs - HPGl Script, a hpgl/2 interpreter, which uses a Postscript *
* API for rendering a scene and thus renders to a variety of *
* devices and fileformats. *
* *
* (C) 2004-2006 ev-i Informationstechnologie GmbH http://www.ev-i.at *
* *
* Author: Wolfgang Glas *
* *
* hpgs is free software; you can redistribute it and/or *
* modify it under the terms of the GNU Lesser General Public *
* License as published by the Free Software Foundation; either *
* version 2.1 of the License, or (at your option) any later version. *
* *
* hpgs is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU *
* Lesser General Public License for more details. *
* *
* You should have received a copy of the GNU Lesser General Public *
* License along with this library; if not, write to the *
* Free Software Foundation, Inc., 59 Temple Place, Suite 330, *
* Boston, MA 02111-1307 USA *
* *
***********************************************************************
* *
* The implementation of the PJL interpreter. *
* *
***********************************************************************/
#include <hpgsreader.h>
#include <math.h>
#include <string.h>
#include <ctype.h>
#include <errno.h>
//#define HPGS_PJL_DEBUG
static int pjl_read_line (hpgs_reader *reader, char term, char *buf, size_t buf_size)
{
int i=0;
while ((reader->last_byte = hpgs_getc(reader->in)) != EOF)
{
if (i == 0 && reader->last_byte== HPGS_ESC)
{
hpgs_ungetc(reader->last_byte,reader->in);
return -2;
}
if (reader->last_byte==term)
{
while ((reader->last_byte = hpgs_getc(reader->in)) != EOF)
if (!isspace(reader->last_byte))
{
hpgs_ungetc(reader->last_byte,reader->in);
break;
}
while (i > 0 && (buf[i-1]=='\0' || isspace(buf[i-1])))
--i;
if (i<buf_size) buf[i]='\0';
return i;
}
if (reader->last_byte == '\n' && i==4 && strncmp(buf,"@PJL",4)==0)
{
i=0;
continue;
}
if (reader->last_byte == '\n') continue;
if (reader->last_byte != '\r' && i<buf_size)
{
buf[i] = (i < buf_size-1) ? (char)reader->last_byte : '\0';
++i;
}
}
return EOF;
}
/*!
Read a PJL block of the file.
Return values:
\li -1 Error, unexpected EOF.
\li 0 Success, ESC found, continue with ESC evaluation.
\li 1 Success, return to HPGL context.
\li 2 Success, plotsize set, skip interpretation of file.
\li 3 Success, go to PCL context.
*/
int hpgs_reader_do_PJL(hpgs_reader *reader)
{
char buf[256];
int r,arg,arg_sign;
int x_size = 0;
int y_size = 0;
reader->bytes_ignored = 0;
reader->eoc = 0;
size_t pos = 0;
while ((r=pjl_read_line(reader,' ',buf,sizeof(buf))) != EOF)
{
if (r==-2) return 0; // ESC found.
// HPGL autodetection.
if (pos >= 0 && r>=2 &&
buf[0] >= 'A' && buf[0] <= 'Z' &&
buf[1] >= 'A' && buf[1] <= 'Z' )
{
if (hpgs_istream_seek(reader->in,pos))
return -1;
// overtake PCL papersize, if given.
if (x_size > 0 && y_size > 0)
{
// PJL paper sizes are apparently in PCL units.
x_size *= reader->pcl_scale/HP_TO_PT;
y_size *= reader->pcl_scale/HP_TO_PT;
if (reader->verbosity)
hpgs_log(hpgs_i18n("Setting PJL papersize %dx%d.\n"),x_size,y_size);
switch (hpgs_reader_set_plotsize(reader,x_size,y_size))
{
case 2:
return 2;
case 0:
break;
default:
return -1;
}
}
// return to HPGL context.
return 1;
}
if (strcmp(buf,"@PJL"))
return hpgs_set_error(hpgs_i18n("Illegal line heading <%s> in PJL."),buf);
if (pjl_read_line(reader,' ',buf,sizeof(buf)) < 0)
return -1;
if (strcmp(buf,"SET") == 0)
{
if (pjl_read_line(reader,'=',buf,sizeof(buf)) < 0)
return -1;
if (strcmp(buf,"PAPERLENGTH") == 0)
{
switch (hpgs_reader_read_pcl_int(reader,&arg,&arg_sign))
{
case -1:
return -1;
case 1:
break;
default:
return hpgs_set_error(hpgs_i18n("Missing number in PJL SET PAPERLENGTH."));
}
x_size = arg;
}
else if (strcmp(buf,"PAPERWIDTH") == 0)
{
switch (hpgs_reader_read_pcl_int(reader,&arg,&arg_sign))
{
case -1:
return -1;
case 1:
break;
default:
return hpgs_set_error(hpgs_i18n("Missing number in PJL SET PAPERWIDTH."));
}
y_size = arg;
}
else if (strcmp(buf,"RESOLUTION") == 0)
{
switch (hpgs_reader_read_pcl_int(reader,&arg,&arg_sign))
{
case -1:
return -1;
case 1:
break;
default:
return hpgs_set_error(hpgs_i18n("Missing number in PJL SET RESOLUTION."));
}
reader->pcl_scale = 72.0/(double)arg;
reader->pcl_raster_res = arg;
}
}
else if (strcmp(buf,"ENTER") == 0)
{
if (pjl_read_line(reader,'=',buf,sizeof(buf)) < 0)
return -1;
if (strcmp(buf,"LANGUAGE") == 0)
{
if (pjl_read_line(reader,'\n',buf,sizeof(buf)) < 0)
return -1;
if (x_size > 0 && y_size > 0)
{
// PJL paper sizes are apparently in PCL units.
x_size *= reader->pcl_scale/HP_TO_PT;
y_size *= reader->pcl_scale/HP_TO_PT;
if (reader->verbosity)
hpgs_log(hpgs_i18n("Setting PJL papersize %dx%d\n"),x_size,y_size);
switch (hpgs_reader_set_plotsize(reader,x_size,y_size))
{
case 2:
return 2;
case 0:
break;
default:
return -1;
}
}
if (strcmp(buf,"HPGL2") == 0 ||
strcmp(buf,"HPGL/2") == 0 ||
strcmp(buf,"HP-GL2") == 0 ||
strcmp(buf,"HP-GL/2") == 0 )
{
// probe for escape character
if ((reader->last_byte = hpgs_getc(reader->in)) == EOF)
return -1;
hpgs_ungetc(reader->last_byte,reader->in);
return reader->last_byte == HPGS_ESC ? 0 : 1;
}
else if (strcmp(buf,"PCL3GUI") == 0 ||
strcmp(buf,"PCL3") == 0 ||
strcmp(buf,"PCL5") == 0 )
return 3;
else
return hpgs_set_error(hpgs_i18n("Invalid language <%s> in PJL ENTER LANGUAGE."),
buf);
}
}
if (pjl_read_line(reader,'\n',buf,sizeof(buf)) < 0)
return -1;
// store position for HPGL autodetection.
if (hpgs_istream_tell(reader->in,&pos))
return hpgs_set_error(hpgs_i18n("Cannot get file position in PJL interpretation."));
}
return -1;
}

View File

@ -0,0 +1,87 @@
/***********************************************************************
* *
* $Id: hpgsplugin.h 325 2006-04-22 20:01:11Z softadm $
* *
* hpgs - HPGl Script, a hpgl/2 interpreter, which uses a Postscript *
* API for rendering a scene and thus renders to a variety of *
* devices and fileformats. *
* *
* (C) 2004-2006 ev-i Informationstechnologie GmbH http://www.ev-i.at *
* *
* Author: Wolfgang Glas *
* *
* hpgs is free software; you can redistribute it and/or *
* modify it under the terms of the GNU Lesser General Public *
* License as published by the Free Software Foundation; either *
* version 2.1 of the License, or (at your option) any later version. *
* *
* hpgs is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU *
* Lesser General Public License for more details. *
* *
* You should have received a copy of the GNU Lesser General Public *
* License along with this library; if not, write to the *
* Free Software Foundation, Inc., 59 Temple Place, Suite 330, *
* Boston, MA 02111-1307 USA *
* *
***********************************************************************
* *
* The extension classes located in my device plugin. *
* *
***********************************************************************/
#ifndef __HPGS_PLUGIN_H
#define __HPGS_PLUGIN_H
#include<hpgs.h>
#ifdef __cplusplus
extern "C" {
#endif
#ifdef HPGS_SHARED
# ifdef WIN32
# ifdef __GNUC__
# ifdef HPGS_BUILD_PLUGIN
# define HPGS_PLUGIN_API __attribute__((dllexport))
# else
# define HPGS_PLUGIN_API __attribute__((dllimport))
# endif
# else
# ifdef HPGS_BUILD_PLUGIN
# define HPGS_PLUGIN_API __declspec(dllexport)
# else
# define HPGS_PLUGIN_API __declspec(dllimport)
# endif
# endif
# else
# define HPGS_PLUGIN_API
# endif
#else
# define HPGS_PLUGIN_API
#endif
HPGS_PLUGIN_API int hpgs_plugin_new_device(hpgs_device **device,
void **asset_ctxt,
hpgs_reader_asset_func_t *page_asset_func,
void **frame_asset_ctxt,
hpgs_reader_asset_func_t *frame_asset_func,
const char *dev_name,
const char *out_fn,
const hpgs_bbox *bb,
double xres, double yres,
hpgs_bool do_rop3,
int argc, const char *argv[]);
HPGS_PLUGIN_API void hpgs_plugin_version(int * major, int *minor);
HPGS_PLUGIN_API void hpgs_plugin_init();
HPGS_PLUGIN_API void hpgs_plugin_cleanup();
#ifdef __cplusplus
} // end of extern "C"
#endif
#endif /* ! __HPGS_H */

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,515 @@
/***********************************************************************
* *
* $Id: hpgsreader.h 381 2007-02-20 09:06:38Z softadm $
* *
* hpgs - HPGl Script, a hpgl/2 interpreter, which uses a Postscript *
* API for rendering a scene and thus renders to a variety of *
* devices and fileformats. *
* *
* (C) 2004-2006 ev-i Informationstechnologie GmbH http://www.ev-i.at *
* *
* Author: Wolfgang Glas *
* *
* hpgs is free software; you can redistribute it and/or *
* modify it under the terms of the GNU Lesser General Public *
* License as published by the Free Software Foundation; either *
* version 2.1 of the License, or (at your option) any later version. *
* *
* hpgs is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU *
* Lesser General Public License for more details. *
* *
* You should have received a copy of the GNU Lesser General Public *
* License along with this library; if not, write to the *
* Free Software Foundation, Inc., 59 Temple Place, Suite 330, *
* Boston, MA 02111-1307 USA *
* *
***********************************************************************
* *
* Private subroutines used by the hpgs_reader. *
* *
***********************************************************************/
#ifndef __HPGS_READER_H__
#define __HPGS_READER_H__
#include <hpgs.h>
#ifdef __cplusplus
extern "C" {
#endif
/*! \file hpgsreader.h
\brief The private interfaces for implementing the HPGL reader.
A header file, which declares the private structures and functions
used to implement the HPGL reader \c hpgs_reader.
*/
#define HPGS_MAX_PCL_PALETTES 20
#define MM_TO_PT (72.0 / 25.4)
#define HP_TO_PT (72.0 / (25.4 * 40.0))
#define MAKE_COMMAND(a,b) (((int)(a) << 8) + (b))
#define AA_CMD MAKE_COMMAND('A','A')
#define AC_CMD MAKE_COMMAND('A','C')
#define AD_CMD MAKE_COMMAND('A','D')
#define AR_CMD MAKE_COMMAND('A','R')
#define AT_CMD MAKE_COMMAND('A','T')
#define BP_CMD MAKE_COMMAND('B','P')
#define BR_CMD MAKE_COMMAND('B','R')
#define BZ_CMD MAKE_COMMAND('B','Z')
#define CI_CMD MAKE_COMMAND('C','I')
#define CO_CMD MAKE_COMMAND('C','O')
#define CP_CMD MAKE_COMMAND('C','P')
#define CR_CMD MAKE_COMMAND('C','R')
#define DI_CMD MAKE_COMMAND('D','I')
#define DR_CMD MAKE_COMMAND('D','R')
#define DT_CMD MAKE_COMMAND('D','T')
#define DV_CMD MAKE_COMMAND('D','V')
#define EA_CMD MAKE_COMMAND('E','A')
#define EP_CMD MAKE_COMMAND('E','P')
#define ER_CMD MAKE_COMMAND('E','R')
#define ES_CMD MAKE_COMMAND('E','S')
#define EW_CMD MAKE_COMMAND('E','W')
#define FP_CMD MAKE_COMMAND('F','P')
#define FR_CMD MAKE_COMMAND('F','R')
#define FT_CMD MAKE_COMMAND('F','T')
#define IN_CMD MAKE_COMMAND('I','N')
#define IP_CMD MAKE_COMMAND('I','P')
#define IR_CMD MAKE_COMMAND('I','R')
#define IW_CMD MAKE_COMMAND('I','W')
#define LA_CMD MAKE_COMMAND('L','A')
#define LB_CMD MAKE_COMMAND('L','B')
#define LO_CMD MAKE_COMMAND('L','O')
#define LT_CMD MAKE_COMMAND('L','T')
#define MC_CMD MAKE_COMMAND('M','C')
#define MG_CMD MAKE_COMMAND('M','G')
#define NP_CMD MAKE_COMMAND('N','P')
#define PA_CMD MAKE_COMMAND('P','A')
#define PC_CMD MAKE_COMMAND('P','C')
#define PD_CMD MAKE_COMMAND('P','D')
#define PE_CMD MAKE_COMMAND('P','E')
#define PG_CMD MAKE_COMMAND('P','G')
#define PM_CMD MAKE_COMMAND('P','M')
#define PP_CMD MAKE_COMMAND('P','P')
#define PR_CMD MAKE_COMMAND('P','R')
#define PS_CMD MAKE_COMMAND('P','S')
#define PU_CMD MAKE_COMMAND('P','U')
#define PW_CMD MAKE_COMMAND('P','W')
#define RA_CMD MAKE_COMMAND('R','A')
#define RO_CMD MAKE_COMMAND('R','O')
#define RR_CMD MAKE_COMMAND('R','R')
#define RT_CMD MAKE_COMMAND('R','T')
#define SA_CMD MAKE_COMMAND('S','A')
#define SC_CMD MAKE_COMMAND('S','C')
#define SD_CMD MAKE_COMMAND('S','D')
#define SI_CMD MAKE_COMMAND('S','I')
#define SL_CMD MAKE_COMMAND('S','L')
#define SM_CMD MAKE_COMMAND('S','M')
#define SP_CMD MAKE_COMMAND('S','P')
#define SR_CMD MAKE_COMMAND('S','R')
#define SS_CMD MAKE_COMMAND('S','S')
#define TR_CMD MAKE_COMMAND('T','R')
#define UL_CMD MAKE_COMMAND('U','L')
#define WG_CMD MAKE_COMMAND('W','G')
#define WU_CMD MAKE_COMMAND('W','U')
/*! @addtogroup reader
* @{
*/
typedef struct hpgs_reader_poly_point_st hpgs_reader_poly_point;
/*! \brief A point in hte HPGL polygon buffer
This structure holds a point in the polygon buffer of HPGL
used to implement PM, EP and FP commands.
*/
struct hpgs_reader_poly_point_st
{
hpgs_point p; //!< The coordinates of the point
int flag; //!< 0 moveto, 1 lineto, 2 curveto
};
typedef struct hpgs_reader_pcl_palette_st hpgs_reader_pcl_palette;
/*! \brief A PCL palette as used by PCL push/pop palette.
This structure holds all properties which are saved/resoterd through PCL push/pop palette.
*/
struct hpgs_reader_pcl_palette_st
{
hpgs_palette_color colors[256]; /*!< The palette colors. */
hpgs_palette_color last_color; /*!< The PCL color currently being assembled. */
int cid_space; /*!< The current PCL color space. */
int cid_enc; /*!< The current PCL pixel encoding scheme. */
int cid_bpi; /*!< PCL Bits per color index. */
int cid_bpc[3];/*!< PCL Bits per color component. */
};
/*! \brief A HPGL interpreter.
This structure holds all the states used during the interpretation
of a HPGL stream. Users of the library usually don't have to cope
with details of this structure.
*/
struct hpgs_reader_st
{
hpgs_istream *in; /*!< The current input stream. */
hpgs_device *device; /*!< The current output device. */
hpgs_device *plotsize_device; /*!< The current plotsize device. */
int current_page; /*!< The number of the current page. -1...single page mode. */
int verbosity; /*!< The verbosity level in effect. */
double lw_factor; /*!< The linewidth scaling factor. */
/*@{ */
/*! The paper size in PostScript pt (1/72 inch). */
double x_size,y_size; /*@} */
/*@{ */
/*! The frame advance vector in PostScript pt (1/72 inch). */
double frame_x,frame_y; /*@} */
hpgs_point P1; /*!< HPGL frame point P1 in PostScript pt (1/72 inch). */
hpgs_point P2; /*!< HPGL frame point P2 in PostScript pt (1/72 inch). */
hpgs_point delta_P; /*!< The difference of P2-P1 as set by the IP command. */
int rotation; /*!< The current rotation angle (90/180/270/360). */
/*@{ */
/*! The current effective coordinate scaling of a SC command. */
int sc_type;
double sc_xmin;
double sc_xmax;
double sc_ymin;
double sc_ymax;
double sc_left;
double sc_bottom;
/*@} */
int rop3; /*!< ROP3 operation in effect. */
hpgs_bool src_transparency; /*!< ROP3 source transparency. */
hpgs_bool pattern_transparency; /*!< ROP3 pattern transparency. */
hpgs_matrix world_matrix; /*!< transformation matrix for the transformation of HPGL to PostScript
(world) coordinates usually given in points (1/72 inch). */
double world_scale; /*!< sqrt(|det(world_matrix)|) */
hpgs_matrix page_matrix; /*!< transformation matrix for the transformation of
PostScript (world) coordinates usually given in points (1/72 inch)
to user defined page-coorindates. */
double page_scale; /*!< sqrt(|det(page_matrix)|) */
hpgs_matrix total_matrix; /*!< The concatenation of page_matrix and world_matrix. */
double total_scale; /*!< sqrt(|det(page_matrix)|) */
int page_mode; /*!< 0...untransformed, 1...fixed page, 2...dynamic page */
double page_width; /*!< The page width or the maximal page width in points. */
double page_height; /*!< The page height or the maximal page height in points. */
double page_angle; /*!< The rotation angle of the HPGL content on the page. */
double page_border; /*!< The border of the HPGL border on the page. */
hpgs_bbox page_bbox; /*!< The currently active page bounding box. */
hpgs_bbox content_bbox; /*!< The bounding box of the HPGL content of the current page. */
void *page_asset_ctxt; /*!< A callback for rendering additional page assets before showpage. */
hpgs_reader_asset_func_t page_asset_func; /*!< A callback for rendering additional page assets before showpage. */
void *frame_asset_ctxt; /*!< A callback for rendering additional frame assets before frame advance/showpage. */
hpgs_reader_asset_func_t frame_asset_func; /*!< A callback for rendering additional frame asset before frame advance/showpage. */
/*@{ */
/*! linetype settings. (-8,...8) stored from 0...16 */
int linetype_nsegs[17];
float linetype_segs[17][20];
/*@} */
/*@{ */
/*! pen settings */
int npens;
double *pen_widths;
hpgs_color *pen_colors;
/*@} */
hpgs_color min_color; /*!< The minimal RGB values. */
hpgs_color max_color; /*!< The maximal RGB values. */
/*@{ */
/*! label terminator settings */
char label_term;
int label_term_ignore;
/*@} */
int polygon_mode; /*!< Are we in polygon mode? */
/*@{ */
/*! the polygon buffer used in polygon mode. */
hpgs_reader_poly_point *poly_buffer;
int poly_buffer_size;
int poly_buffer_alloc_size;
/*@} */
int polygon_open; /*!< Is a polygon currently open? */
int pen_width_relative; /*!< Are pen widths specified relative? */
int pen_down; /*!< Is the pen down? */
int current_pen; /*!< Number of the current pen. */
int current_linetype; /*!< Number of the current linetype. */
int absolute_plotting; /*!< Are PU and PD coordinates absoulte, because a PA statement is in effect? */
int have_current_point; /*!< Do we have a current pen position, aka current_point is a valid position. */
hpgs_point current_point; /*!< The current pen position in PostScript pt (1/72 inch),
if \c have_current_point is true. */
hpgs_point first_path_point;/*!< The first point in a path, if \c polygon_open is true. */
hpgs_point min_path_point; /*!< The minimal x/y coordinates of all points in an open path. */
hpgs_point max_path_point; /*!< The maximal x/y coordinates of all points in an open path. */
hpgs_point anchor_point; /*!< The anchor point for fill patterns. */
int current_ft; /*!< The fill type currently in effect. */
double ft3_angle; /*!< The current pattern angle of fill type 3. */
double ft3_spacing;/*!< The current pattern spacing of fill type 3. */
double ft4_angle; /*!< The current pattern angle of fill type 4. */
double ft4_spacing;/*!< The current pattern spacing of fill type 4. */
double ft10_level; /*!< The current color level for fill type 10. */
/*@{ */
/*! the text state for the standard font. */
int default_encoding;
int default_face;
int default_spacing;
double default_pitch;
double default_height;
int default_posture;
int default_weight;
/*@} */
/*@{ */
/*! the text state for the alternate font. */
int alternate_encoding;
int alternate_face;
int alternate_spacing;
double alternate_pitch;
double alternate_height;
int alternate_posture;
int alternate_weight;
/*@} */
int alternate_font; /*!< do we use the alternate font? */
/*@{ */
/*! text attributes set through special commands. */
hpgs_point cr_point;
hpgs_point current_char_size;
hpgs_point current_extra_space;
double current_slant;
int current_label_origin;
int current_text_path;
int current_text_line;
double current_label_angle;
/*@} */
double pcl_scale; /*!< The factor from PCL units to PostScript pt (1/72 inch). */
double pcl_hmi; /*!< PCL horizontal motion index in pt. */
double pcl_vmi; /*!< PCL vertical motion index in pt. */
hpgs_point pcl_point; /*!< PCL point position in pt. */
hpgs_reader_pcl_palette *pcl_palettes[HPGS_MAX_PCL_PALETTES]; /*!< The PCL palette stack of palattes fo 256 colors .*/
int pcl_i_palette; /*!< The number of of the current PCL palette on the stack. */
int pcl_raster_mode; /*!< The PCL ratser mode.
-1 no raster graphics, 0 horizontal graphics, 3 vertical graphics */
int pcl_raster_presentation;/*!< The PCL raster presentation mode. */
int pcl_raster_src_width; /*!< The PCL raster image source width. */
int pcl_raster_src_height; /*!< The PCL raster image source height. */
int pcl_raster_dest_width; /*!< The PCL raster image destination width. */
int pcl_raster_dest_height; /*!< The PCL raster image destination height. */
int pcl_raster_res; /*!< The PCL raster image resolution. */
int pcl_raster_compression; /*!< The PCL raster compression in effect. */
int pcl_raster_y_offset; /*!< The PCL raster y offset in effect. */
int pcl_raster_plane; /*!< The current PCL raster plane for transfer data by plane. */
int pcl_raster_line; /*!< The number of the raster line currently transferred. */
unsigned char *pcl_raster_data[8];/*!< The buffer for the data of the current raster. One pointer per plane. */
int pcl_raster_data_size; /*!< The size of the raster data buffer. */
int pcl_raster_planes; /*!< The number of planes of the raster data currently being transferred. */
hpgs_image *pcl_image; /*!< The image currently filled by pcl. */
// The filename for dumped pcl images.
int png_dump_count; /*!< The number of PCL images dumped so far. */
char *png_dump_filename; /*!< The base filename for dumped PCL images. */
int clipsave_depth; /*!< how many clipsaves have been issued? */
int last_byte; /*!< The last byte extracted from the stream? */
int bytes_ignored;/*!< A byte counter for various purposes. */
int eoc; /*!< Did we reach the end of a HPGL command? */
hpgs_bool interrupted; /*!< Did someone call \c hpgs_reader_interrupt ? */
};
HPGS_INTERNAL_API int hpgs_reader_check_param_end(hpgs_reader *reader);
/*! read an integer argument from the stream - PCL version.
return values:
\li -1 read error/EOF
\li 0 no integer found.
\li 1 integer found.
*/
HPGS_INTERNAL_API int hpgs_reader_read_pcl_int(hpgs_reader *reader, int *x, int *sign);
/*! read an integer argument from the stream .
return values:
\li -1 read error/EOF
\li 0 success.
\li 1 End of command.
*/
HPGS_INTERNAL_API int hpgs_reader_read_int(hpgs_reader *reader, int *x);
/*" read a double argument from the stream.
return values:
\li -1 read error/EOF
\li 0 success.
\li 1 End of command.
*/
HPGS_INTERNAL_API int hpgs_reader_read_double(hpgs_reader *reader, double *x);
HPGS_INTERNAL_API int hpgs_reader_read_point(hpgs_reader *reader, hpgs_point *p, int xform);
/* read a new string argument from the stream
return values:
\li -1 read error/EOF
\li 0 success.
\li 1 End of command.
*/
HPGS_INTERNAL_API int hpgs_reader_read_new_string(hpgs_reader *reader, char *str);
HPGS_INTERNAL_API int hpgs_reader_read_label_string(hpgs_reader *reader, char *str);
HPGS_INTERNAL_API void hpgs_reader_set_page_matrix (hpgs_reader *reader, const hpgs_bbox *bb);
HPGS_INTERNAL_API void hpgs_reader_set_default_transformation (hpgs_reader *reader);
HPGS_INTERNAL_API void hpgs_reader_set_default_state (hpgs_reader *reader);
HPGS_INTERNAL_API void hpgs_reader_set_defaults (hpgs_reader *reader);
HPGS_INTERNAL_API int hpgs_reader_set_plotsize (hpgs_reader *reader, double xs, double ys);
HPGS_INTERNAL_API int hpgs_reader_showpage (hpgs_reader *reader, int ipage);
HPGS_INTERNAL_API void hpgs_reader_set_std_pen_colors(hpgs_reader *reader,
int i0, int n);
HPGS_INTERNAL_API int hpgs_reader_checkpath(hpgs_reader *reader);
HPGS_INTERNAL_API int hpgs_reader_moveto(hpgs_reader *reader, hpgs_point *p);
HPGS_INTERNAL_API int hpgs_reader_lineto(hpgs_reader *reader, hpgs_point *p);
HPGS_INTERNAL_API int hpgs_reader_curveto(hpgs_reader *reader,
hpgs_point *p1, hpgs_point *p2, hpgs_point *p3);
HPGS_INTERNAL_API int hpgs_reader_stroke(hpgs_reader *reader);
HPGS_INTERNAL_API int hpgs_reader_fill(hpgs_reader *reader, hpgs_bool winding);
HPGS_INTERNAL_API int hpgs_reader_closepath(hpgs_reader *reader);
HPGS_INTERNAL_API int hpgs_reader_do_setpen(hpgs_reader *reader, int pen);
HPGS_INTERNAL_API int hpgs_reader_label(hpgs_reader *reader,
const char *str, int str_len,
int face,
int encoding,
int posture,
int weight,
const hpgs_point *left_vec,
const hpgs_point *up_vec,
const hpgs_point *space_vec);
HPGS_INTERNAL_API int hpgs_device_label(hpgs_device *dev,
hpgs_point *pos,
const char *str, int str_len,
int face,
const char *encoding,
int posture,
int weight,
const hpgs_point *left_vec,
const hpgs_point *up_vec,
const hpgs_point *space_vec);
typedef int (*hpgs_reader_hpglcmd_func_t)(hpgs_reader *reader);
HPGS_INTERNAL_API int hpgs_reader_do_PCL(hpgs_reader *reader, hpgs_bool take_pos);
HPGS_INTERNAL_API int hpgs_reader_do_PJL(hpgs_reader *reader);
HPGS_INTERNAL_API int hpgs_reader_push_pcl_palette (hpgs_reader *reader);
HPGS_INTERNAL_API int hpgs_reader_pop_pcl_palette (hpgs_reader *reader);
HPGS_INTERNAL_API int hpgs_reader_do_AA(hpgs_reader *reader);
HPGS_INTERNAL_API int hpgs_reader_do_AC(hpgs_reader *reader);
HPGS_INTERNAL_API int hpgs_reader_do_AD(hpgs_reader *reader);
HPGS_INTERNAL_API int hpgs_reader_do_AR(hpgs_reader *reader);
HPGS_INTERNAL_API int hpgs_reader_do_AT(hpgs_reader *reader);
HPGS_INTERNAL_API int hpgs_reader_do_BP(hpgs_reader *reader);
HPGS_INTERNAL_API int hpgs_reader_do_BR(hpgs_reader *reader);
HPGS_INTERNAL_API int hpgs_reader_do_BZ(hpgs_reader *reader);
HPGS_INTERNAL_API int hpgs_reader_do_CI(hpgs_reader *reader);
HPGS_INTERNAL_API int hpgs_reader_do_CO(hpgs_reader *reader);
HPGS_INTERNAL_API int hpgs_reader_do_CP(hpgs_reader *reader);
HPGS_INTERNAL_API int hpgs_reader_do_CR(hpgs_reader *reader);
HPGS_INTERNAL_API int hpgs_reader_do_DI(hpgs_reader *reader);
HPGS_INTERNAL_API int hpgs_reader_do_DR(hpgs_reader *reader);
HPGS_INTERNAL_API int hpgs_reader_do_DT(hpgs_reader *reader);
HPGS_INTERNAL_API int hpgs_reader_do_DV(hpgs_reader *reader);
HPGS_INTERNAL_API int hpgs_reader_do_EA(hpgs_reader *reader);
HPGS_INTERNAL_API int hpgs_reader_do_EP(hpgs_reader *reader);
HPGS_INTERNAL_API int hpgs_reader_do_ER(hpgs_reader *reader);
HPGS_INTERNAL_API int hpgs_reader_do_ES(hpgs_reader *reader);
HPGS_INTERNAL_API int hpgs_reader_do_EW(hpgs_reader *reader);
HPGS_INTERNAL_API int hpgs_reader_do_FP(hpgs_reader *reader);
HPGS_INTERNAL_API int hpgs_reader_do_FR(hpgs_reader *reader);
HPGS_INTERNAL_API int hpgs_reader_do_FT(hpgs_reader *reader);
HPGS_INTERNAL_API int hpgs_reader_do_IN(hpgs_reader *reader);
HPGS_INTERNAL_API int hpgs_reader_do_IP(hpgs_reader *reader);
HPGS_INTERNAL_API int hpgs_reader_do_IR(hpgs_reader *reader);
HPGS_INTERNAL_API int hpgs_reader_do_IW(hpgs_reader *reader);
HPGS_INTERNAL_API int hpgs_reader_do_LA(hpgs_reader *reader);
HPGS_INTERNAL_API int hpgs_reader_do_LB(hpgs_reader *reader);
HPGS_INTERNAL_API int hpgs_reader_do_LO(hpgs_reader *reader);
HPGS_INTERNAL_API int hpgs_reader_do_LT(hpgs_reader *reader);
HPGS_INTERNAL_API int hpgs_reader_do_MC(hpgs_reader *reader);
HPGS_INTERNAL_API int hpgs_reader_do_MG(hpgs_reader *reader);
HPGS_INTERNAL_API int hpgs_reader_do_NP(hpgs_reader *reader);
HPGS_INTERNAL_API int hpgs_reader_do_PC(hpgs_reader *reader);
HPGS_INTERNAL_API int hpgs_reader_do_PA(hpgs_reader *reader);
HPGS_INTERNAL_API int hpgs_reader_do_PD(hpgs_reader *reader);
HPGS_INTERNAL_API int hpgs_reader_do_PE(hpgs_reader *reader);
HPGS_INTERNAL_API int hpgs_reader_do_PG(hpgs_reader *reader);
HPGS_INTERNAL_API int hpgs_reader_do_PM(hpgs_reader *reader);
HPGS_INTERNAL_API int hpgs_reader_do_PP(hpgs_reader *reader);
HPGS_INTERNAL_API int hpgs_reader_do_PR(hpgs_reader *reader);
HPGS_INTERNAL_API int hpgs_reader_do_PS(hpgs_reader *reader);
HPGS_INTERNAL_API int hpgs_reader_do_PU(hpgs_reader *reader);
HPGS_INTERNAL_API int hpgs_reader_do_PW(hpgs_reader *reader);
HPGS_INTERNAL_API int hpgs_reader_do_RA(hpgs_reader *reader);
HPGS_INTERNAL_API int hpgs_reader_do_RO(hpgs_reader *reader);
HPGS_INTERNAL_API int hpgs_reader_do_RR(hpgs_reader *reader);
HPGS_INTERNAL_API int hpgs_reader_do_RT(hpgs_reader *reader);
HPGS_INTERNAL_API int hpgs_reader_do_SA(hpgs_reader *reader);
HPGS_INTERNAL_API int hpgs_reader_do_SC(hpgs_reader *reader);
HPGS_INTERNAL_API int hpgs_reader_do_SD(hpgs_reader *reader);
HPGS_INTERNAL_API int hpgs_reader_do_SI(hpgs_reader *reader);
HPGS_INTERNAL_API int hpgs_reader_do_SL(hpgs_reader *reader);
HPGS_INTERNAL_API int hpgs_reader_do_SM(hpgs_reader *reader);
HPGS_INTERNAL_API int hpgs_reader_do_SP(hpgs_reader *reader);
HPGS_INTERNAL_API int hpgs_reader_do_SR(hpgs_reader *reader);
HPGS_INTERNAL_API int hpgs_reader_do_SS(hpgs_reader *reader);
HPGS_INTERNAL_API int hpgs_reader_do_TR(hpgs_reader *reader);
HPGS_INTERNAL_API int hpgs_reader_do_UL(hpgs_reader *reader);
HPGS_INTERNAL_API int hpgs_reader_do_WG(hpgs_reader *reader);
HPGS_INTERNAL_API int hpgs_reader_do_WU(hpgs_reader *reader);
/*! @} */ /* end of group reader */
#ifdef __cplusplus
} // end of extern "C"
#endif
#endif // ! __HPGS_READER_H__

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,627 @@
/***********************************************************************
* *
* $Id: hpgssetup.c 362 2006-10-16 14:13:48Z softadm $
* *
* hpgs - HPGl Script, a hpgl/2 interpreter, which uses a Postscript *
* API for rendering a scene and thus renders to a variety of *
* devices and fileformats. *
* *
* (C) 2004-2006 ev-i Informationstechnologie GmbH http://www.ev-i.at *
* *
* Author: Wolfgang Glas *
* *
* hpgs is free software; you can redistribute it and/or *
* modify it under the terms of the GNU Lesser General Public *
* License as published by the Free Software Foundation; either *
* version 2.1 of the License, or (at your option) any later version. *
* *
* hpgs is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU *
* Lesser General Public License for more details. *
* *
* You should have received a copy of the GNU Lesser General Public *
* License along with this library; if not, write to the *
* Free Software Foundation, Inc., 59 Temple Place, Suite 330, *
* Boston, MA 02111-1307 USA *
* *
***********************************************************************
* *
* The implementation of the HPGL reader. *
* *
***********************************************************************/
#include <hpgsreader.h>
#include <math.h>
#include <string.h>
#include <ctype.h>
#include <errno.h>
/*
Standard values.
*/
static hpgs_color std_pen_colors[8] =
{
{ 1.0, 1.0, 1.0 },
{ 0.0, 0.0, 0.0 },
{ 1.0, 0.0, 0.0 },
{ 0.0, 1.0, 0.0 },
{ 1.0, 1.0, 0.0 },
{ 0.0, 0.0, 1.0 },
{ 1.0, 0.0, 1.0 },
{ 0.0, 1.0, 1.0 }
};
static double std_pen_widths[8] =
{
1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0
};
static int std_linetype_nsegs[17] =
{
9, 7, 7, 5, 5, 3, 3, 3, 0, 2, 2, 2, 4, 4, 6, 6, 8
};
static float std_linetype_segs[17][20] =
{
{24, 10, 1, 10, 10, 10, 1, 10, 24, 0,0,0,0,0,0,0,0,0,0,0},
{34, 10, 1, 10, 1, 10, 34, 0, 0, 0,0,0,0,0,0,0,0,0,0,0},
{25, 10, 10, 10, 10, 10, 25, 0, 0, 0,0,0,0,0,0,0,0,0,0,0},
{35, 10, 10, 10, 35, 0, 0, 0, 0, 0,0,0,0,0,0,0,0,0,0,0},
{40, 10, 1, 10, 39, 0, 0, 0, 0, 0,0,0,0,0,0,0,0,0,0,0},
{35, 30, 35, 0, 0, 0, 0, 0, 0, 0,0,0,0,0,0,0,0,0,0,0},
{25, 50, 25, 0, 0, 0, 0, 0, 0, 0,0,0,0,0,0,0,0,0,0,0},
{ 1, 99, 0, 0, 0, 0, 0, 0, 0, 0,0,0,0,0,0,0,0,0,0,0},
{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,0,0,0,0,0,0,0,0,0,0},
{ 1, 99, 0, 0, 0, 0, 0, 0, 0, 0,0,0,0,0,0,0,0,0,0,0},
{50, 50, 0, 0, 0, 0, 0, 0, 0, 0,0,0,0,0,0,0,0,0,0,0},
{70, 30, 0, 0, 0, 0, 0, 0, 0, 0,0,0,0,0,0,0,0,0,0,0},
{79, 10, 1, 10, 0, 0, 0, 0, 0, 0,0,0,0,0,0,0,0,0,0,0},
{70, 10, 10, 10, 0, 0, 0, 0, 0, 0,0,0,0,0,0,0,0,0,0,0},
{50, 10, 10, 10, 10, 10, 0, 0, 0, 0,0,0,0,0,0,0,0,0,0,0},
{68, 10, 1, 10, 1, 10, 0, 0, 0, 0,0,0,0,0,0,0,0,0,0,0},
{48, 10, 1, 10, 10, 10, 1, 10, 0, 0,0,0,0,0,0,0,0,0,0,0}
};
void hpgs_reader_set_default_state (hpgs_reader *reader)
{
reader->frame_x=0.0;
reader->frame_y=0.0;
reader->x_size = 47520.0 * HP_TO_PT;
reader->y_size = 33600.0 * HP_TO_PT;
reader->P1.x = 0.0;
reader->P1.y = 0.0;
reader->P2.x = reader->x_size;
reader->P2.y = reader->y_size;
reader->delta_P.x = reader->P2.x - reader->P1.x;
reader->delta_P.y = reader->P2.y - reader->P1.y;
reader->rotation=0;
reader->sc_type=-1;
reader->sc_xmin=0.0;
reader->sc_xmax=1.0;
reader->sc_ymin=0.0;
reader->sc_ymax=1.0;
reader->sc_left = 50.0;
reader->sc_bottom = 50.0;
hpgs_reader_set_default_transformation (reader);
reader->rop3 = 252;
reader->src_transparency = HPGS_TRUE;
reader->pattern_transparency = HPGS_TRUE;
reader->pen_down = 0;
reader->pen_width_relative = 0;
reader->label_term= '\003';
reader->label_term_ignore = 1;
reader->polygon_mode = 0;
reader->poly_buffer_size = 0;
reader->polygon_open = 0;
reader->have_current_point = 0;
reader->current_point.x = reader->page_matrix.dx;
reader->current_point.y = reader->page_matrix.dy;
reader->current_pen = 0;
reader->current_linetype = 0;
reader->absolute_plotting = 1;
reader->anchor_point.x = 0.0;
reader->anchor_point.y = 0.0;
reader->current_ft = 1;
reader->ft3_angle = 0.0;
reader->ft3_spacing = 0.0;
reader->ft4_angle = 0.0;
reader->ft4_spacing = 0.0;
reader->ft10_level = 100.0;
reader->default_encoding = 0;
reader->default_face = 0;
reader->default_spacing = 0;
reader->default_pitch = 9.0;
reader->default_height = 11.5;
reader->default_posture = 0;
reader->default_weight = 0;
reader->alternate_encoding = 0;
reader->alternate_face = 0;
reader->alternate_spacing = 0;
reader->alternate_pitch = 9.0;
reader->alternate_height = 11.5;
reader->alternate_posture = 0;
reader->alternate_weight = 0;
reader->alternate_font = 0;
reader->cr_point = reader->current_point;
reader->current_char_size.x = 0.0;
reader->current_char_size.y = 0.0;
reader->current_extra_space.x = 0.0;
reader->current_extra_space.y = 0.0;
reader->current_slant = 0.0;
reader->current_label_origin = 1;
reader->current_text_path = 0;
reader->current_text_line = 0;
reader->current_label_angle = 0.0;
// standard linetypes. (-8,...8)
memcpy(reader->linetype_nsegs,std_linetype_nsegs,sizeof(std_linetype_nsegs));
memcpy(reader->linetype_segs,std_linetype_segs,sizeof(std_linetype_segs));
}
void hpgs_reader_set_std_pen_colors(hpgs_reader *reader,
int i0, int n)
{
int n_std = sizeof(std_pen_colors)/sizeof(hpgs_color);
if (i0 >= n_std) return;
if (n <= 0) return;
if (i0+n >= n_std) n = n_std-i0;
memcpy(reader->pen_colors+i0,std_pen_colors+i0,sizeof(hpgs_color)*n);
}
static hpgs_reader_pcl_palette *hpgs_reader_new_pcl_palette ()
{
hpgs_reader_pcl_palette *ret=(hpgs_reader_pcl_palette *)malloc(sizeof(hpgs_reader_pcl_palette));
if (!ret) return 0;
memset(ret->colors,0,sizeof(hpgs_palette_color)*256);
ret->colors[0].r = 0xff;
ret->colors[0].g = 0xff;
ret->colors[0].b = 0xff;
ret->last_color.r = 0;
ret->last_color.g = 0;
ret->last_color.b = 0;
ret->cid_space = 0;
ret->cid_enc = 1;
ret->cid_bpi = 1;
ret->cid_bpc[0] = 8;
ret->cid_bpc[1] = 8;
ret->cid_bpc[2] = 8;
return ret;
}
static hpgs_reader_pcl_palette *hpgs_reader_dup_pcl_palette (const hpgs_reader_pcl_palette *p)
{
hpgs_reader_pcl_palette *ret=(hpgs_reader_pcl_palette *)malloc(sizeof(hpgs_reader_pcl_palette));
if (!ret) return 0;
memcpy(ret,p,sizeof(hpgs_reader_pcl_palette));
return ret;
}
static void hpgs_reader_destroy_pcl_palette (hpgs_reader_pcl_palette *p)
{
if (p)
free(p);
}
int hpgs_reader_push_pcl_palette (hpgs_reader *reader)
{
if (reader->pcl_i_palette >= HPGS_MAX_PCL_PALETTES-1)
return hpgs_set_error(hpgs_i18n("PCL palette stack overflow (maximal stack size = %d)."),
HPGS_MAX_PCL_PALETTES);
if (reader->pcl_i_palette >= 0)
reader->pcl_palettes[reader->pcl_i_palette+1] =
hpgs_reader_dup_pcl_palette (reader->pcl_palettes[reader->pcl_i_palette]);
else
reader->pcl_palettes[reader->pcl_i_palette+1] =
hpgs_reader_new_pcl_palette ();
if (!reader->pcl_palettes[reader->pcl_i_palette+1])
return hpgs_set_error(hpgs_i18n("Out of memory pushing PCL palette."));
++reader->pcl_i_palette;
return 0;
}
int hpgs_reader_pop_pcl_palette (hpgs_reader *reader)
{
if (reader->pcl_i_palette <= 0)
return hpgs_set_error(hpgs_i18n("PCL palette stack underflow."));
hpgs_reader_destroy_pcl_palette(reader->pcl_palettes[reader->pcl_i_palette]);
--reader->pcl_i_palette;
return 0;
}
void hpgs_reader_set_defaults (hpgs_reader *reader)
{
int i;
if (reader->pen_widths)
free(reader->pen_widths);
if (reader->pen_colors)
free(reader->pen_colors);
if (reader->poly_buffer)
free(reader->poly_buffer);
// standard pen widths.
reader->npens = 8;
reader->pen_widths = (double*)malloc(sizeof(std_pen_widths));
memcpy(reader->pen_widths,std_pen_widths,sizeof(std_pen_widths));
reader->pen_colors = (hpgs_color *)malloc(sizeof(std_pen_colors));
memcpy(reader->pen_colors,std_pen_colors,sizeof(std_pen_colors));
reader->min_color.r=0.0;
reader->min_color.g=0.0;
reader->min_color.b=0.0;
reader->max_color.r=255.0;
reader->max_color.g=255.0;
reader->max_color.b=255.0;
reader->poly_buffer_alloc_size = 256;
reader->poly_buffer_size = 0;
reader->poly_buffer = (hpgs_reader_poly_point *)
malloc(sizeof(hpgs_reader_poly_point)*reader->poly_buffer_alloc_size);
hpgs_reader_set_default_state (reader);
reader->clipsave_depth = 0;
for (i=0;i<=reader->pcl_i_palette;++i)
hpgs_reader_destroy_pcl_palette(reader->pcl_palettes[i]);
reader->pcl_i_palette = -1;
hpgs_reader_push_pcl_palette(reader);
for (i=0;i<8;++i)
if (reader->pcl_raster_data[i])
{
free(reader->pcl_raster_data[i]);
reader->pcl_raster_data[i] = 0;
}
if (reader->pcl_image)
hpgs_image_destroy(reader->pcl_image);
reader->pcl_scale = 72.0/300.0;
reader->pcl_hmi = 7.2;
reader->pcl_vmi = 12.0;
reader->pcl_point.x = 0.0;
reader->pcl_point.y = 0.0;
reader->pcl_raster_mode = -1;
reader->pcl_raster_presentation = 0;
reader->pcl_raster_src_width = 0;
reader->pcl_raster_src_height = 0;
reader->pcl_raster_dest_width = 0;
reader->pcl_raster_dest_height = 0;
reader->pcl_raster_res = 75;
reader->pcl_raster_compression = 0;
reader->pcl_raster_y_offset = 0;
reader->pcl_raster_plane = 0;
reader->pcl_raster_line = 0;
reader->pcl_raster_data_size = 0;
reader->pcl_raster_planes = 1;
reader->pcl_image=0;
reader->bytes_ignored = 0;
reader->eoc = 0;
}
/* initializes the device */
static int init_device(hpgs_reader *reader)
{
hpgs_color pat = { 0.0,0.0,0.0 };
reader->rop3 = 252;
reader->src_transparency = HPGS_TRUE;
reader->pattern_transparency = HPGS_TRUE;
if (hpgs_setlinejoin(reader->device,hpgs_join_miter)) return -1;
if (hpgs_setlinecap(reader->device,hpgs_cap_butt)) return -1;
if (hpgs_setmiterlimit(reader->device,5.0)) return -1;
if (hpgs_setrop3(reader->device,
reader->rop3,
reader->src_transparency,
reader->pattern_transparency)) return -1;
if (hpgs_setpatcol(reader->device,&pat)) return -1;
return 0;
}
/*
HPGL command BP (Begin Plot)
*/
int hpgs_reader_do_BP (hpgs_reader *reader)
{
while (!reader->eoc)
{
int kind;
int dummy;
char header[HPGS_MAX_LABEL_SIZE];
if (hpgs_reader_read_int(reader,&kind)) return -1;
if (reader->eoc) return 0;
switch (kind)
{
case 1:
if (hpgs_reader_read_new_string(reader,header)) return -1;
if (reader->verbosity)
hpgs_log(hpgs_i18n("Plot Title: %.*s\n"),HPGS_MAX_LABEL_SIZE,header);
break;
case 2:
case 3:
case 4:
case 5:
if (hpgs_reader_read_int(reader,&dummy)) return -1;
break;
default:
return -1;
}
}
return init_device(reader);
}
/*
HPGL command CO (COmment)
*/
int hpgs_reader_do_CO (hpgs_reader *reader)
{
char comment[HPGS_MAX_LABEL_SIZE];
if (reader->eoc) return 0;
if (hpgs_reader_read_new_string(reader,comment)) return -1;
if (reader->verbosity)
hpgs_log(hpgs_i18n("Comment: %.*s\n"),HPGS_MAX_LABEL_SIZE,comment);
return reader->eoc ? 0 : -1;
}
/*
HPGL command IN (Initialize Plot)
*/
int hpgs_reader_do_IN (hpgs_reader *reader)
{
int i;
if (hpgs_reader_checkpath(reader)) return -1;
if (!reader->eoc)
{
int dummy;
if (hpgs_reader_read_int(reader,&dummy)) return -1;
}
while (reader->clipsave_depth > 0)
{
hpgs_cliprestore(reader->device);
--reader->clipsave_depth;
}
hpgs_reader_set_default_state (reader);
for (i=0;i<reader->npens;++i)
reader->pen_widths[i] = 1.0;
return init_device(reader);
}
/*
Internal function, which calls the page asset callback and
does a showpage on the device.
*/
int hpgs_reader_showpage (hpgs_reader *reader, int ipage)
{
if (hpgs_reader_checkpath(reader)) return -1;
while (reader->clipsave_depth > 0)
{
hpgs_cliprestore(reader->device);
--reader->clipsave_depth;
}
if (reader->frame_asset_func)
{
hpgs_bbox frame_bbox;
frame_bbox.llx = reader->frame_x == 0.0 ? reader->content_bbox.llx : reader->frame_x;
frame_bbox.lly = reader->content_bbox.lly;
frame_bbox.urx = reader->content_bbox.urx;
frame_bbox.ury = reader->content_bbox.ury;
if (frame_bbox.urx > frame_bbox.llx)
{
int ipage = reader->current_page;
if (reader->frame_asset_func(reader->frame_asset_ctxt,
reader->device,
&reader->page_matrix,
&reader->total_matrix,
&frame_bbox,ipage <= 1 ? 0 : ipage-1) )
return -1;
}
}
if (reader->page_asset_func &&
reader->page_asset_func(reader->page_asset_ctxt,
reader->device,
&reader->page_matrix,
&reader->total_matrix,
&reader->content_bbox,ipage <= 1 ? 0 : ipage-1) )
return -1;
return hpgs_showpage(reader->device,ipage);
}
/*
HPGL command PG (advance PaGe)
*/
int hpgs_reader_do_PG(hpgs_reader *reader)
{
int ret;
ret = hpgs_reader_showpage(reader,reader->current_page);
if (ret) return -1;
++reader->current_page;
// if wee are not in singlepage mode,
// try to set the individual page size.
if (reader->current_page > 0 &&
reader->plotsize_device &&
(hpgs_device_capabilities(reader->device) & HPGS_DEVICE_CAP_MULTISIZE))
{
hpgs_bbox page_bb;
int ret = hpgs_getplotsize(reader->plotsize_device,reader->current_page,&page_bb);
if (ret < 0) return -1;
// if ret is 1, we got the overall bounding box and the plotsize device
// knows about no more pages.
// So we stop the interpretation at this point.
return 2;
// set the plotsize of the next page.
if (reader->verbosity)
hpgs_log(hpgs_i18n("Bounding Box of Page %d: %g %g %g %g.\n"),
reader->current_page,
page_bb.llx,page_bb.lly,
page_bb.urx,page_bb.ury );
// change the page layout.
hpgs_reader_set_page_matrix(reader,&page_bb);
hpgs_reader_set_default_transformation(reader);
if (hpgs_setplotsize(reader->device,&reader->page_bbox) < 0)
return -1;
}
// stop the interpretation, if we are in singlepage mode.
return reader->current_page > 0 ? 0 : 2;
}
/*
HPGL command UL (User defined Linetype)
*/
int hpgs_reader_do_UL (hpgs_reader *reader)
{
int itype,nsegs;
if (reader->eoc)
{
memcpy(reader->linetype_nsegs,std_linetype_nsegs,sizeof(std_linetype_nsegs));
memcpy(reader->linetype_segs,std_linetype_segs,sizeof(std_linetype_segs));
return 0;
}
if (hpgs_reader_read_int(reader,&itype)) return -1;
if (itype < -8 || itype > 8)
return hpgs_set_error(hpgs_i18n("Illegal linetype %d given."),itype);
if (reader->eoc)
{
memcpy(reader->linetype_segs[8+itype],
std_linetype_segs[8+itype],sizeof(std_linetype_segs[0]));
memcpy(reader->linetype_segs[8-itype],
std_linetype_segs[8-itype],sizeof(std_linetype_segs[0]));
reader->linetype_nsegs[8+itype] = std_linetype_nsegs[8+itype];
reader->linetype_nsegs[8+itype] = std_linetype_nsegs[8-itype];
return 0;
}
nsegs = 0;
while (!reader->eoc)
{
double gap;
if (hpgs_reader_read_double(reader,&gap)) return -1;
reader->linetype_segs[8+itype][nsegs] = gap;
reader->linetype_segs[8-itype][nsegs] = gap;
++nsegs;
}
reader->linetype_nsegs[8+itype] = nsegs;
reader->linetype_nsegs[8-itype] = nsegs;
return 0;
}
/*
HPGL command MC (Merge Control)
*/
int hpgs_reader_do_MC (hpgs_reader *reader)
{
int mode=0,rop=252;
if (!reader->eoc &&
hpgs_reader_read_int(reader,&mode)) return -1;
if (!reader->eoc &&
hpgs_reader_read_int(reader,&rop)) return -1;
reader->rop3 = mode ? rop : 252;
return hpgs_setrop3(reader->device,reader->rop3,
reader->src_transparency,
reader->pattern_transparency );
}
/*
HPGL command TR (Transparency Mode)
*/
int hpgs_reader_do_TR (hpgs_reader *reader)
{
int n=1;
if (!reader->eoc &&
hpgs_reader_read_int(reader,&n)) return -1;
reader->src_transparency = (n != 0);
return hpgs_setrop3(reader->device,reader->rop3,
reader->src_transparency,
reader->pattern_transparency );
}

View File

@ -0,0 +1,773 @@
/***********************************************************************
* *
* $Id: hpgstransform.c 362 2006-10-16 14:13:48Z softadm $
* *
* hpgs - HPGl Script, a hpgl/2 interpreter, which uses a Postscript *
* API for rendering a scene and thus renders to a variety of *
* devices and fileformats. *
* *
* (C) 2004-2006 ev-i Informationstechnologie GmbH http://www.ev-i.at *
* *
* Author: Wolfgang Glas *
* *
* hpgs is free software; you can redistribute it and/or *
* modify it under the terms of the GNU Lesser General Public *
* License as published by the Free Software Foundation; either *
* version 2.1 of the License, or (at your option) any later version. *
* *
* hpgs is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU *
* Lesser General Public License for more details. *
* *
* You should have received a copy of the GNU Lesser General Public *
* License along with this library; if not, write to the *
* Free Software Foundation, Inc., 59 Temple Place, Suite 330, *
* Boston, MA 02111-1307 USA *
* *
***********************************************************************
* *
* The implementation of the HPGL reader. *
* *
***********************************************************************/
#include <hpgsreader.h>
#include <math.h>
//#define HPGS_DEBUG_XFORM
static void apply_scale(hpgs_reader *reader,
const hpgs_point *p1, const hpgs_point *p2)
{
double xf,yf;
double dx = 0.0,dy=0.0;
hpgs_point p2u;
if (reader->sc_type < 0) return;
// get P2 in old user coordinates
p2u.x = reader->frame_x + p2->x * HP_TO_PT;
p2u.y = reader->frame_y + p2->y * HP_TO_PT;
hpgs_matrix_ixform(&p2u,&p2u,&reader->world_matrix);
#ifdef HPGS_DEBUG_XFORM
{
hpgs_point p1u;
p1u.x = reader->frame_x + p1->x * HP_TO_PT;
p1u.y = reader->frame_y + p1->y * HP_TO_PT;
hpgs_matrix_ixform(&p1u,&reader->world_matrix,&p1u);
hpgs_log("SC: P1 = %g,%g.\n",p1->x,p1->y);
hpgs_log("SC: P2 = %g,%g.\n",p2->x,p2->y);
hpgs_log("SC: p1u = %g,%g.\n",p1u.x,p1u.y);
hpgs_log("SC: p2u = %g,%g.\n",p2u.x,p2u.y);
hpgs_log("SC: xmin,xmax = %g,%g.\n",reader->sc_xmin,reader->sc_xmax);
hpgs_log("SC: ymin,ymax = %g,%g.\n",reader->sc_ymin,reader->sc_ymax);
}
#endif
switch (reader->sc_type)
{
case 0:
xf = p2u.x / (reader->sc_xmax - reader->sc_xmin);
yf = p2u.y / (reader->sc_ymax - reader->sc_ymin);
break;
case 1:
xf = p2u.x / (reader->sc_xmax - reader->sc_xmin);
yf = p2u.y / (reader->sc_ymax - reader->sc_ymin);
if (xf < yf)
{
dy = (yf-xf) * (reader->sc_ymax - reader->sc_ymin) * 0.01 * reader->sc_left;
yf = xf;
}
else
{
dx = (xf-yf) * (reader->sc_xmax - reader->sc_xmin) * 0.01 * reader->sc_bottom;
xf = yf;
}
break;
case 2:
xf = reader->sc_xmax;
yf = reader->sc_ymax;
break;
default:
return;
}
#ifdef HPGS_DEBUG_XFORM
hpgs_log("SC: xf,yf = %g,%g.\n",xf,yf);
#endif
dx -= reader->sc_xmin * xf;
dy -= reader->sc_ymin * yf;
// concatenate transofrmation matrices.
//
// | 1 0 0 | | 1 0 0 |
// | x0 mxx mxy |* | dx xf 0 | =
// | y0 myx myy | | dy 0 yf |
//
// | 1 0 0 |
// | x0+mxx*dx+mxy*dy mxx*xf mxy*yf |
// | y0+myx*dx+myy*dy myx*xf myy*yf |
//
reader->world_matrix.dx += reader->world_matrix.mxx*dx + reader->world_matrix.mxy*dy;
reader->world_matrix.dy += reader->world_matrix.myx*dx + reader->world_matrix.myy*dy;
reader->world_matrix.mxx *= xf;
reader->world_matrix.myx *= xf;
reader->world_matrix.mxy *= yf;
reader->world_matrix.myy *= yf;
#ifdef HPGS_DEBUG_XFORM
hpgs_log("SC: %10g %10g %10g\n",reader->world_matrix.dx,reader->world_matrix.mxx,reader->world_matrix.mxy);
hpgs_log("SC: %10g %10g %10g\n",reader->world_matrix.dy,reader->world_matrix.myx,reader->world_matrix.myy);
#endif
}
void hpgs_reader_set_default_transformation (hpgs_reader *reader)
{
// transformation matrix for user to PS coordinates.
int angle = reader->y_size >= reader->x_size ? 90 : 0;
hpgs_point p1 = reader->P1;
hpgs_point p2 = reader->P2;
angle += reader->rotation;
if ((angle % 180) == 90)
{
p2.y -= p1.y;
p1.y = 0.0;
}
reader->world_matrix.dx = reader->frame_x + p1.x * HP_TO_PT;
reader->world_matrix.dy = reader->frame_y + p1.y * HP_TO_PT;
switch (angle % 360)
{
case 90:
reader->world_matrix.mxx = 0.0;
reader->world_matrix.mxy = -HP_TO_PT;
reader->world_matrix.myx = HP_TO_PT;
reader->world_matrix.myy = 0.0;
break;
case 180:
reader->world_matrix.mxx = -HP_TO_PT;
reader->world_matrix.mxy = 0.0;
reader->world_matrix.myx = 0.0;
reader->world_matrix.myy = -HP_TO_PT;
break;
case 270:
reader->world_matrix.mxx = 0.0;
reader->world_matrix.mxy = HP_TO_PT;
reader->world_matrix.myx = -HP_TO_PT;
reader->world_matrix.myy = 0.0;
break;
default: // 0
reader->world_matrix.mxx = HP_TO_PT;
reader->world_matrix.mxy = 0.0;
reader->world_matrix.myx = 0.0;
reader->world_matrix.myy = HP_TO_PT;
}
#ifdef HPGS_DEBUG_XFORM
hpgs_log("xform: %10g %10g %10g\n",reader->world_matrix.dx,reader->world_matrix.mxx,reader->world_matrix.mxy);
hpgs_log("xform: %10g %10g %10g\n",reader->world_matrix.dy,reader->world_matrix.myx,reader->world_matrix.myy);
#endif
apply_scale(reader,&p1,&p2);
reader->world_scale =
sqrt (fabs(reader->world_matrix.mxx * reader->world_matrix.myy -
reader->world_matrix.mxy * reader->world_matrix.myx ) );
// finally transform from model space to the page.
hpgs_matrix_concat(&reader->total_matrix,&reader->page_matrix,&reader->world_matrix);
reader->total_scale = reader->page_scale * reader->world_scale;
}
/*
HPGL command PS (Plot Size)
*/
int hpgs_reader_do_PS (hpgs_reader *reader)
{
double x_size=reader->x_size/HP_TO_PT;
double y_size=reader->y_size/HP_TO_PT;
if (reader->eoc)
{
// Well it seems, that some oldstyle HPGL files use
// PS w/o arguments in order to enforce a coordinate setup
// as if a portrait paper size has been selected.
// (resulting in a prerotation of 90 degrees).
x_size = 33600.0;
y_size = 47520.0;
}
else
{
if (hpgs_reader_read_double(reader,&x_size)) return -1;
// set y-size to sqrt(0.5) * x_size in order to prevent
// the picture from rotation. This is better then setting
// the y-size to the (fictional) hard-clip limit, because
// without rotation we definitely can calculate our own plotsize
// using -i.
if (reader->eoc)
y_size = sqrt(0.5) * x_size;
}
if (!reader->eoc &&
hpgs_reader_read_double(reader,&y_size)) return -1;
return hpgs_reader_set_plotsize (reader,x_size,y_size);
}
/*
Actually set the plot size. User by PS command above and by PJL parser.
*/
int hpgs_reader_set_plotsize (hpgs_reader *reader, double x_size, double y_size)
{
hpgs_bbox bb = { 0.0,0.0,x_size*HP_TO_PT,y_size*HP_TO_PT };
reader->x_size = x_size;
reader->y_size = y_size;
if (y_size >= x_size)
{
reader->P1.x = x_size;
reader->P1.y = 0.0;
reader->P2.x = 0.0;
reader->P2.y = y_size;
}
else
{
reader->P1.x = 0.0;
reader->P1.y = 0.0;
reader->P2.x = x_size;
reader->P2.y = y_size;
}
reader->delta_P.x = reader->P2.x - reader->P1.x;
reader->delta_P.y = reader->P2.y - reader->P1.y;
// undo any effects from an RO or SC statement.
reader->rotation = 0;
reader->sc_type = -1;
// change the page matrix only, if we don't have a plotsize device.
if (!reader->plotsize_device)
hpgs_reader_set_page_matrix (reader,&bb);
hpgs_reader_set_default_transformation(reader);
// report plot size only if
// when we don't have a plotsize device at hands.
if (reader->plotsize_device)
return 0;
return hpgs_setplotsize(reader->device,&reader->page_bbox);
}
/*
Change the page matrix according to this content bounding box.
*/
void hpgs_reader_set_page_matrix (hpgs_reader *reader, const hpgs_bbox *bb)
{
hpgs_bbox rbb;
double xscale,yscale;
hpgs_point rcp;
hpgs_matrix_ixform(&rcp,&reader->current_point,&reader->page_matrix);
// save the content bounding box for propagating it to the
// page_asset function.
reader->content_bbox = *bb;
if (reader->page_mode == 0)
{
reader->page_bbox = *bb;
hpgs_matrix_set_identity(&reader->page_matrix);
reader->page_scale = 1.0;
goto restore_cb;
}
reader->page_matrix.mxx = cos(reader->page_angle * M_PI / 180.0);
reader->page_matrix.mxy = -sin(reader->page_angle * M_PI / 180.0);
reader->page_matrix.myx = sin(reader->page_angle * M_PI / 180.0);
reader->page_matrix.myy = cos(reader->page_angle * M_PI / 180.0);
reader->page_matrix.dx = 0.0;
reader->page_matrix.dy = 0.0;
if (reader->page_mode == 2) // dynamic page.
{
hpgs_matrix_xform_bbox(&rbb,&reader->page_matrix,bb);
reader->page_bbox.llx = 0.0;
reader->page_bbox.lly = 0.0;
reader->page_bbox.urx = (rbb.urx-rbb.llx) + 2.0 * reader->page_border;
reader->page_bbox.ury = (rbb.ury-rbb.lly) + 2.0 * reader->page_border;
reader->page_matrix.dx = reader->page_border - rbb.llx;
reader->page_matrix.dy = reader->page_border - rbb.lly;
// do we fit on the maximal page size?
if ((reader->page_width <= 0.0 || reader->page_bbox.urx <= reader->page_width) &&
(reader->page_height <= 0.0 || reader->page_bbox.ury <= reader->page_height) )
{
reader->page_scale = 1.0;
goto restore_cb;
}
if (reader->page_bbox.urx > reader->page_width)
xscale = reader->page_width/reader->page_bbox.urx;
else
xscale = 1.0;
if (reader->page_bbox.ury> reader->page_height)
yscale = reader->page_height/reader->page_bbox.ury;
else
yscale = 1.0;
reader->page_scale = HPGS_MIN(xscale,yscale);
double rscale = 0.0;
double xx = 1.0;
// transform the scale to a human-interceptable scale.
do
{
xx *= 0.1;
rscale = floor(reader->page_scale / xx);
}
while (rscale < 2.0);
reader->page_scale = rscale * xx;
reader->page_matrix.mxx *= reader->page_scale;
reader->page_matrix.mxy *= reader->page_scale;
reader->page_matrix.myx *= reader->page_scale;
reader->page_matrix.myy *= reader->page_scale;
reader->page_matrix.dx *= reader->page_scale;
reader->page_matrix.dy *= reader->page_scale;
reader->page_bbox.urx *= reader->page_scale;
reader->page_bbox.ury *= reader->page_scale;
goto restore_cb;
}
// fixed page.
reader->page_bbox.llx = 0.0;
reader->page_bbox.lly = 0.0;
reader->page_bbox.urx = reader->page_width;
reader->page_bbox.ury = reader->page_height;
hpgs_matrix_xform_bbox(&rbb,&reader->page_matrix,bb);
xscale = (reader->page_width - 2.0 * reader->page_border) / (rbb.urx-rbb.llx);
yscale = (reader->page_height - 2.0 * reader->page_border) / (rbb.ury-rbb.lly);
reader->page_scale = HPGS_MIN(xscale,yscale);
reader->page_matrix.mxx *= reader->page_scale;
reader->page_matrix.mxy *= reader->page_scale;
reader->page_matrix.myx *= reader->page_scale;
reader->page_matrix.myy *= reader->page_scale;
if (reader->page_scale == xscale)
{
reader->page_matrix.dx = reader->page_border - reader->page_scale * rbb.llx;
reader->page_matrix.dy =
0.5 * (reader->page_height - reader->page_scale * (rbb.ury-rbb.lly)) - reader->page_scale * rbb.lly;
}
else
{
reader->page_matrix.dx =
0.5 * (reader->page_width - reader->page_scale * (rbb.urx-rbb.llx)) - reader->page_scale * rbb.llx;
reader->page_matrix.dy = reader->page_border - reader->page_scale * rbb.lly;
}
restore_cb:
hpgs_matrix_xform(&reader->current_point,&reader->page_matrix,&rcp);
}
/*
HPGL command FR (advance FRame)
*/
int hpgs_reader_do_FR (hpgs_reader *reader)
{
double advance = reader->x_size;
if (!reader->eoc)
{
if (hpgs_reader_read_double(reader,&advance)) return -1;
}
if (hpgs_reader_checkpath(reader)) return -1;
while (reader->clipsave_depth > 0)
{
hpgs_cliprestore(reader->device);
--reader->clipsave_depth;
}
if (reader->frame_asset_func)
{
hpgs_bbox frame_bbox;
frame_bbox.llx = reader->frame_x == 0.0 ? reader->content_bbox.llx : reader->frame_x;
frame_bbox.lly = reader->content_bbox.lly;
frame_bbox.urx = reader->frame_x + advance * HP_TO_PT;
frame_bbox.ury = reader->content_bbox.ury;
if (frame_bbox.urx > frame_bbox.llx)
{
int ipage = reader->current_page;
if (reader->frame_asset_func(reader->frame_asset_ctxt,
reader->device,
&reader->page_matrix,
&reader->total_matrix,
&frame_bbox,ipage <= 1 ? 0 : ipage-1) )
return -1;
}
}
reader->frame_x += advance * HP_TO_PT;
reader->P1.x -= advance;
reader->P2.x -= advance;
return 0;
}
/*
HPGL command RO (ROtate)
*/
int hpgs_reader_do_RO (hpgs_reader *reader)
{
int rot=0;
hpgs_point p1,p2;
double dx,dy;
if (!reader->eoc &&
hpgs_reader_read_int(reader,&rot)) return -1;
switch ((rot - reader->rotation) % 360)
{
case 90:
p1.x = -reader->P1.y;
p1.y = reader->P1.x;
p2.x = -reader->P2.y;
p2.y = reader->P2.x;
break;
case 180:
p1.x = -reader->P1.x;
p1.y = -reader->P1.y;
p2.x = -reader->P2.x;
p2.y = -reader->P2.x;
break;
case 270:
p1.x = reader->P1.y;
p1.y = -reader->P1.x;
p2.x = reader->P2.y;
p2.y = -reader->P2.x;
break;
default: /* 0,360 */
p1.x = reader->P1.x;
p1.y = reader->P1.y;
p2.x = reader->P2.x;
p2.y = reader->P2.x;
break;
}
dx = p1.x < p2.x ? p1.x : p2.x;
dy = p1.y < p2.y ? p1.y : p2.y;
#ifdef HPGS_DEBUG_XFORM
hpgs_log("RO: rot_old,rot = %d,%d.\n",reader->rotation,rot);
hpgs_log("RO: P1 = %g,%g.\n",reader->P1.x,reader->P1.y);
hpgs_log("RO: P2 = %g,%g.\n",reader->P2.x,reader->P2.y);
#endif
reader->P1.x = p1.x-dx;
reader->P1.y = p1.y-dy;
reader->P2.x = p2.x-dx;
reader->P2.y = p2.y-dy;
#ifdef HPGS_DEBUG_XFORM
hpgs_log("RO: P1 = %g,%g.\n",reader->P1.x,reader->P1.y);
hpgs_log("RO: P2 = %g,%g.\n",reader->P2.x,reader->P2.y);
#endif
reader->rotation = rot;
hpgs_reader_set_default_transformation(reader);
return 0;
}
/*
HPGL command SC (SCale)
*/
int hpgs_reader_do_SC (hpgs_reader *reader)
{
double xmin,xmax,ymin,ymax,left=50.0,bottom=50.0;
int type=0;
if (reader->eoc)
{
reader->sc_type = -1;
hpgs_reader_set_default_transformation(reader);
return 0;
}
if (hpgs_reader_read_double(reader,&xmin)) return -1;
if (reader->eoc) return -1;
if (hpgs_reader_read_double(reader,&xmax)) return -1;
if (reader->eoc) return -1;
if (hpgs_reader_read_double(reader,&ymin)) return -1;
if (reader->eoc) return -1;
if (hpgs_reader_read_double(reader,&ymax)) return -1;
if (!reader->eoc &&
hpgs_reader_read_int(reader,&type)) return -1;
if (type == 1 && !reader->eoc)
{
if (hpgs_reader_read_double(reader,&left)) return -1;
if (reader->eoc) return -1;
if (hpgs_reader_read_double(reader,&bottom)) return -1;
}
reader->sc_type = type;
reader->sc_xmin = xmin;
reader->sc_xmax = xmax;
reader->sc_ymin = ymin;
reader->sc_ymax = ymax;
reader->sc_bottom = bottom;
reader->sc_left = left;
hpgs_reader_set_default_transformation(reader);
return 0;
}
/*
HPGL command IP (Input Point)
*/
int hpgs_reader_do_IP (hpgs_reader *reader)
{
// get default input point.
int angle = reader->y_size >= reader->x_size ? 90 : 0;
angle += reader->rotation;
switch (angle % 360)
{
case 90:
reader->P1.x = reader->x_size;
reader->P1.y = 0.0;
reader->P2.x = 0.0;
reader->P2.y = reader->y_size;
break;
case 180:
break;
reader->P1.x = reader->x_size;
reader->P1.y = reader->y_size;
reader->P2.x = 0.0;
reader->P2.y = 0.0;
break;
case 270:
reader->P1.x = 0.0;
reader->P1.y = reader->y_size;
reader->P2.x = reader->x_size;
reader->P2.y = 0.0;
break;
default: /* 0 */
reader->P1.x = 0.0;
reader->P1.y = 0.0;
reader->P2.x = reader->x_size;
reader->P2.y = reader->y_size;
}
// read input point
if (!reader->eoc)
{
if (hpgs_reader_read_double(reader,
angle%180 ?
&reader->P1.y :
&reader->P1.x )) return -1;
if (reader->eoc) return -1;
if (hpgs_reader_read_double(reader,angle%180 ?
&reader->P2.x :
&reader->P1.y )) return -1;
}
if (!reader->eoc)
{
if (hpgs_reader_read_double(reader,
angle%180 ?
&reader->P2.y :
&reader->P2.x )) return -1;
if (reader->eoc) return -1;
if (hpgs_reader_read_double(reader,
angle%180 ?
&reader->P1.x :
&reader->P2.y )) return -1;
}
reader->delta_P.x = reader->P2.x - reader->P1.x;
reader->delta_P.y = reader->P2.y - reader->P1.y;
#ifdef HPGS_DEBUG_XFORM
hpgs_log("IP: angle = %d.\n",angle);
hpgs_log("IP: P1 = %g,%g.\n",reader->P1.x,reader->P1.y);
hpgs_log("IP: P2 = %g,%g.\n",reader->P2.x,reader->P2.y);
#endif
reader->sc_type = -1;
hpgs_reader_set_default_transformation(reader);
return 0;
}
/*
HPGL command IR (Input point Relative)
*/
int hpgs_reader_do_IR (hpgs_reader *reader)
{
// get default input point.
double p1x=0.0,p1y=0.0,p2x,p2y;
int angle = reader->y_size >= reader->x_size ? 90 : 0;
angle += reader->rotation;
switch (angle % 360)
{
case 90:
p1x = reader->x_size;
p1y = 0.0;
p2x = 0.0;
p2y = reader->y_size;
break;
case 180:
break;
p1x = reader->x_size;
p1y = reader->y_size;
p2x = 0.0;
p2y = 0.0;
break;
case 270:
p1x = 0.0;
p1y = reader->y_size;
p2x = reader->x_size;
p2y = 0.0;
break;
default:
p1x = 0.0;
p1y = 0.0;
p2x = reader->x_size;
p2y = reader->y_size;
}
// read input point
if (!reader->eoc)
{
double x,y;
if (hpgs_reader_read_double(reader,&x)) return -1;
if (hpgs_reader_read_double(reader,&y)) return -1;
p1x = reader->x_size * x * 0.01;
p2x = p1x + reader->delta_P.x;
p1y = reader->y_size * y * 0.01;
p2y = p1y + reader->delta_P.y;
}
if (!reader->eoc)
{
if (hpgs_reader_read_double(reader,&p2x)) return -1;
if (hpgs_reader_read_double(reader,&p2y)) return -1;
p2x = reader->x_size * p2x * 0.01;
p2y = reader->y_size * p2y * 0.01;
reader->delta_P.x = p2x - p1x;
reader->delta_P.y = p2y - p1y;
}
reader->P1.x = p1x;
reader->P1.y = p1y;
reader->P2.x = p2x;
reader->P2.y = p2y;
#ifdef HPGS_DEBUG_XFORM
hpgs_log("IR: P1 = %g,%g.\n",reader->P1.x,reader->P1.y);
hpgs_log("IR: P2 = %g,%g.\n",reader->P2.x,reader->P2.y);
#endif
hpgs_reader_set_default_transformation(reader);
return 0;
}
/*
HPGL command IW (Input Window)
*/
int hpgs_reader_do_IW (hpgs_reader *reader)
{
// get default input point.
hpgs_point ll;
hpgs_point ur;
hpgs_point p;
if (hpgs_reader_checkpath(reader)) return -1;
while (reader->clipsave_depth > 0)
{
hpgs_cliprestore(reader->device);
--reader->clipsave_depth;
}
if (reader->eoc) return 0;
// read input point
if (hpgs_reader_read_point(reader,&ll,1)) return -1;
if (hpgs_reader_read_point(reader,&ur,1)) return -1;
if (hpgs_clipsave(reader->device)) return -1;
++reader->clipsave_depth;
if (hpgs_newpath(reader->device)) return -1;
if (hpgs_moveto(reader->device,&ll)) return -1;
p.x = ll.x;
p.y = ur.y;
if (hpgs_lineto(reader->device,&p)) return -1;
if (hpgs_lineto(reader->device,&ur)) return -1;
p.x = ur.x;
p.y = ll.y;
if (hpgs_lineto(reader->device,&p)) return -1;
if (hpgs_closepath(reader->device)) return -1;
if (hpgs_clip(reader->device,HPGS_TRUE)) return -1;
reader->have_current_point = 0;
return hpgs_newpath(reader->device);
}

View File

@ -0,0 +1,329 @@
/***********************************************************************
* *
* $Id: hpgszostream.c 368 2006-12-31 15:18:08Z softadm $
* *
* hpgs - HPGl Script, a hpgl/2 interpreter, which uses a Postscript *
* API for rendering a scene and thus renders to a variety of *
* devices and fileformats. *
* *
* (C) 2004-2006 ev-i Informationstechnologie GmbH http://www.ev-i.at *
* *
* Author: Wolfgang Glas *
* *
* hpgs is free software; you can redistribute it and/or *
* modify it under the terms of the GNU Lesser General Public *
* License as published by the Free Software Foundation; either *
* version 2.1 of the License, or (at your option) any later version. *
* *
* hpgs is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU *
* Lesser General Public License for more details. *
* *
* You should have received a copy of the GNU Lesser General Public *
* License along with this library; if not, write to the *
* Free Software Foundation, Inc., 59 Temple Place, Suite 330, *
* Boston, MA 02111-1307 USA *
* *
***********************************************************************
* *
* The implementation of a deflate output stream. *
* *
***********************************************************************/
#include<hpgs.h>
#include<string.h>
#include<zlib.h>
#ifdef WIN32
#include <malloc.h>
#else
#include <alloca.h>
#endif
// Internals of hpgs_z_ostream
typedef struct hpgs_z_ostream_stream_st hpgs_z_ostream_stream;
#define Z_OSTREAM_BUF_SIZE 16384
#define Z_OSTREAM_XFER_SIZE 4096
struct hpgs_z_ostream_stream_st
{
hpgs_ostream *base;
int compression;
hpgs_bool take_base;
unsigned char buffer [Z_OSTREAM_BUF_SIZE];
unsigned char xfer [Z_OSTREAM_XFER_SIZE];
unsigned char *pptr;
int errflg;
z_stream zstream;
size_t total_bytes;
};
static int z_init(hpgs_z_ostream_stream *stream)
{
if (deflateInit(&stream->zstream,stream->compression)==Z_OK)
{
stream->zstream.next_out = (Bytef *)stream->xfer;
stream->zstream.avail_out = sizeof(stream->xfer);
stream->zstream.total_out = 0;
stream->zstream.avail_in = 0;
stream->zstream.total_in = 0;
stream->total_bytes = 0;
return 0;
}
return -1;
}
static int z_consume(hpgs_z_ostream_stream *stream, int flags)
{
int cnt=stream->pptr-stream->buffer;
int zret;
if (stream->errflg)
return EOF;
if (!stream->zstream.next_out && z_init(stream)) return EOF;
if (cnt <= 0 && flags == Z_NO_FLUSH) return 0;
stream->zstream.avail_in=cnt;
stream->zstream.total_in=0;
stream->zstream.next_in=(Bytef *)stream->buffer;
do
{
stream->zstream.avail_out=Z_OSTREAM_XFER_SIZE;
stream->zstream.total_out=0;
stream->zstream.next_out=(Bytef *)stream->xfer;
zret=deflate (&stream->zstream,flags);
if (hpgs_ostream_write(stream->xfer,1,stream->zstream.total_out,stream->base) < stream->zstream.total_out)
{ stream->errflg = 1; return -1; }
}
while (zret == Z_OK &&
stream->zstream.avail_out == 0);
stream->pptr = stream->buffer;
if (stream->zstream.avail_in==0)
{
stream->total_bytes += cnt;
return 0;
}
else
{
stream->errflg = 1;
return -1;
}
}
static int z_putc (int c, hpgs_z_ostream_stream *stream)
{
if (stream->pptr >= stream->buffer + Z_OSTREAM_BUF_SIZE)
z_consume(stream,Z_NO_FLUSH);
if (stream->errflg)
return EOF;
*stream->pptr = c;
++stream->pptr;
return c & 0xff;
}
static int z_write (void *ptr, size_t size, size_t nmemb, hpgs_z_ostream_stream *stream)
{
size_t tot_bytes = size*nmemb;
size_t avail_bytes = stream->buffer + Z_OSTREAM_BUF_SIZE - stream->pptr;
size_t put_bytes = tot_bytes < avail_bytes ? tot_bytes : avail_bytes;
if (stream->errflg)
return EOF;
memcpy(stream->pptr,ptr,put_bytes);
stream->pptr += put_bytes;
while (stream->pptr >= stream->buffer + Z_OSTREAM_BUF_SIZE &&
z_consume(stream,Z_NO_FLUSH) == 0)
{
ptr += put_bytes;
tot_bytes -= put_bytes;
put_bytes = tot_bytes < Z_OSTREAM_BUF_SIZE ? tot_bytes : Z_OSTREAM_BUF_SIZE ;
memcpy(stream->pptr,ptr,put_bytes);
stream->pptr += put_bytes;
}
return stream->errflg ? 0 : nmemb;
}
static int z_vprintf (hpgs_z_ostream_stream *stream, const char *fmt, va_list ap)
{
int n;
size_t size=1024;
char *buf;
while (1)
{
if (stream->errflg)
return EOF;
buf = hpgs_alloca(size);
/* Try to print in the allocated space. */
va_list aq;
va_copy(aq, ap);
#ifdef WIN32
n = _vsnprintf (buf, size, fmt, aq);
#else
n = vsnprintf (buf, size, fmt, aq);
#endif
va_end(aq);
/* If that worked, push the string. */
if (n > -1 && n < size)
return z_write(buf,n,1,stream) ? n : -1;
/* Else try again with more space. */
if (n < 0)
size *= 2;
else
size = n+1;
}
return 0;
}
static int z_flush (hpgs_z_ostream_stream *stream)
{
if (stream->zstream.next_out == 0 && stream->pptr <= stream->buffer) return 0;
int ret = z_consume(stream,Z_FINISH);
deflateEnd (&stream->zstream);
stream->zstream.next_out = 0;
return ret;
}
static int z_close (hpgs_z_ostream_stream *stream)
{
int ret=0;
if (stream->zstream.next_out)
deflateEnd (&stream->zstream);
if (stream->take_base && hpgs_ostream_close(stream->base))
ret = -1;
free(stream);
return ret;
}
static int z_iserror (hpgs_z_ostream_stream *stream)
{
return stream->errflg;
}
static hpgs_istream *z_getbuf (hpgs_z_ostream_stream *stream)
{
z_flush(stream);
return hpgs_ostream_getbuf(stream->base);
}
static int z_tell (hpgs_z_ostream_stream *stream, int layer, size_t *pos)
{
if (layer > 0)
return hpgs_ostream_tell(stream->base,layer-1,pos);
else if (layer == 0)
{
*pos = stream->total_bytes;
return 0;
}
else
return -1;
}
static int z_seek (hpgs_z_ostream_stream *stream, size_t pos)
{
// only seek(0) is supported in order to reuse the stream.
if (pos) return -1;
z_flush(stream);
return hpgs_ostream_seek(stream->base,0);
}
static hpgs_ostream_vtable z_vtable =
{
(hpgs_ostream_putc_func_t) z_putc,
(hpgs_ostream_write_func_t) z_write,
(hpgs_ostream_vprintf_func_t) z_vprintf,
(hpgs_ostream_flush_func_t) z_flush,
(hpgs_ostream_close_func_t) z_close,
(hpgs_ostream_iserror_func_t) z_iserror,
(hpgs_ostream_getbuf_func_t) z_getbuf,
(hpgs_ostream_tell_func_t) z_tell,
(hpgs_ostream_seek_func_t) z_seek,
};
/*! Returns a new \c hpgs_ostream created on the heap,
which operates on a given \c hpgs_ostream and writes
the given data through a zlib deflate stream using
the given compression.
If \c take_base is false, the stream \c base is closed, when
the returned stream is closed. In this case, don't close it at
your own.
Returns a null pointer, when the system is out of memory.
*/
hpgs_ostream *hpgs_new_z_ostream (hpgs_ostream *base, int compression, hpgs_bool take_base)
{
hpgs_z_ostream_stream *stream;
hpgs_ostream *ret = (hpgs_ostream *)malloc(sizeof(hpgs_ostream));
if (!ret)
return 0;
stream =
(hpgs_z_ostream_stream *)malloc(sizeof(hpgs_z_ostream_stream));
if (!stream)
{
free (ret);
return 0;
}
stream->base = base;
stream->compression = compression;
stream->take_base = take_base;
stream->zstream.zalloc = Z_NULL;
stream->zstream.zfree = Z_NULL;
stream->zstream.opaque = Z_NULL;
stream->zstream.next_out = 0;
stream->zstream.avail_out = 0;
stream->zstream.total_out = 0;
stream->zstream.avail_in = 0;
stream->zstream.total_in = 0;
stream->pptr = stream->buffer;
stream->total_bytes = 0;
stream->errflg = 0;
ret->stream = stream;
ret->vtable = &z_vtable;
return ret;
}