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:
parent
bdad0425c4
commit
57f13ad210
@ -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 ;
|
||||
|
67
src/add-ons/translators/hpgs/ConfigView.cpp
Normal file
67
src/add-ons/translators/hpgs/ConfigView.cpp
Normal 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()
|
||||
{
|
||||
}
|
||||
|
19
src/add-ons/translators/hpgs/ConfigView.h
Normal file
19
src/add-ons/translators/hpgs/ConfigView.h
Normal 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 */
|
277
src/add-ons/translators/hpgs/HPGSTranslator.cpp
Normal file
277
src/add-ons/translators/hpgs/HPGSTranslator.cpp
Normal 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();
|
||||
}
|
||||
|
53
src/add-ons/translators/hpgs/HPGSTranslator.h
Normal file
53
src/add-ons/translators/hpgs/HPGSTranslator.h
Normal 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
|
59
src/add-ons/translators/hpgs/Jamfile
Normal file
59
src/add-ons/translators/hpgs/Jamfile
Normal 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 ] ;
|
127
src/add-ons/translators/hpgs/ReadHelper.h
Normal file
127
src/add-ons/translators/hpgs/ReadHelper.h
Normal 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
|
1086
src/add-ons/translators/hpgs/lib/hpgs.c
Normal file
1086
src/add-ons/translators/hpgs/lib/hpgs.c
Normal file
File diff suppressed because it is too large
Load Diff
1218
src/add-ons/translators/hpgs/lib/hpgs.h
Normal file
1218
src/add-ons/translators/hpgs/lib/hpgs.h
Normal file
File diff suppressed because it is too large
Load Diff
176
src/add-ons/translators/hpgs/lib/hpgsbase.c
Normal file
176
src/add-ons/translators/hpgs/lib/hpgsbase.c
Normal 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;
|
||||
}
|
142
src/add-ons/translators/hpgs/lib/hpgsbbox.c
Normal file
142
src/add-ons/translators/hpgs/lib/hpgsbbox.c
Normal 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;
|
||||
}
|
580
src/add-ons/translators/hpgs/lib/hpgsbezier.c
Normal file
580
src/add-ons/translators/hpgs/lib/hpgsbezier.c
Normal 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;
|
||||
}
|
686
src/add-ons/translators/hpgs/lib/hpgscharacter.c
Normal file
686
src/add-ons/translators/hpgs/lib/hpgscharacter.c
Normal 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;
|
||||
}
|
1765
src/add-ons/translators/hpgs/lib/hpgsdevices.c
Normal file
1765
src/add-ons/translators/hpgs/lib/hpgsdevices.c
Normal file
File diff suppressed because it is too large
Load Diff
151
src/add-ons/translators/hpgs/lib/hpgsdevices.h
Normal file
151
src/add-ons/translators/hpgs/lib/hpgsdevices.h
Normal 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 */
|
2205
src/add-ons/translators/hpgs/lib/hpgsfont.c
Normal file
2205
src/add-ons/translators/hpgs/lib/hpgsfont.c
Normal file
File diff suppressed because it is too large
Load Diff
296
src/add-ons/translators/hpgs/lib/hpgsfont.h
Normal file
296
src/add-ons/translators/hpgs/lib/hpgsfont.h
Normal 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
|
629
src/add-ons/translators/hpgs/lib/hpgsglobal.c
Normal file
629
src/add-ons/translators/hpgs/lib/hpgsglobal.c
Normal 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;
|
||||
}
|
112
src/add-ons/translators/hpgs/lib/hpgsgstate.c
Normal file
112
src/add-ons/translators/hpgs/lib/hpgsgstate.c
Normal 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;
|
||||
}
|
75
src/add-ons/translators/hpgs/lib/hpgsi18n.c
Normal file
75
src/add-ons/translators/hpgs/lib/hpgsi18n.c
Normal 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
|
46
src/add-ons/translators/hpgs/lib/hpgsi18n.h
Normal file
46
src/add-ons/translators/hpgs/lib/hpgsi18n.h
Normal 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__
|
1303
src/add-ons/translators/hpgs/lib/hpgsimage.c
Normal file
1303
src/add-ons/translators/hpgs/lib/hpgsimage.c
Normal file
File diff suppressed because it is too large
Load Diff
77
src/add-ons/translators/hpgs/lib/hpgsimage.h
Normal file
77
src/add-ons/translators/hpgs/lib/hpgsimage.h
Normal 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__
|
551
src/add-ons/translators/hpgs/lib/hpgsimagerop.c
Normal file
551
src/add-ons/translators/hpgs/lib/hpgsimagerop.c
Normal 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;
|
||||
}
|
278
src/add-ons/translators/hpgs/lib/hpgsistream.c
Normal file
278
src/add-ons/translators/hpgs/lib/hpgsistream.c
Normal 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;
|
||||
}
|
263
src/add-ons/translators/hpgs/lib/hpgslabel.c
Normal file
263
src/add-ons/translators/hpgs/lib/hpgslabel.c
Normal 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;
|
||||
}
|
353
src/add-ons/translators/hpgs/lib/hpgslexer.c
Normal file
353
src/add-ons/translators/hpgs/lib/hpgslexer.c
Normal 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);
|
||||
}
|
||||
|
223
src/add-ons/translators/hpgs/lib/hpgsmatrix.c
Normal file
223
src/add-ons/translators/hpgs/lib/hpgsmatrix.c
Normal 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;
|
||||
}
|
527
src/add-ons/translators/hpgs/lib/hpgsmkrop.c
Normal file
527
src/add-ons/translators/hpgs/lib/hpgsmkrop.c
Normal 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;
|
||||
}
|
84
src/add-ons/translators/hpgs/lib/hpgsmutex.h
Normal file
84
src/add-ons/translators/hpgs/lib/hpgsmutex.h
Normal 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
|
343
src/add-ons/translators/hpgs/lib/hpgsostream.c
Normal file
343
src/add-ons/translators/hpgs/lib/hpgsostream.c
Normal 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);
|
||||
}
|
716
src/add-ons/translators/hpgs/lib/hpgspaint.c
Normal file
716
src/add-ons/translators/hpgs/lib/hpgspaint.c
Normal 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;
|
||||
}
|
287
src/add-ons/translators/hpgs/lib/hpgspaint.h
Normal file
287
src/add-ons/translators/hpgs/lib/hpgspaint.h
Normal 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 */
|
469
src/add-ons/translators/hpgs/lib/hpgspaintimage.c
Normal file
469
src/add-ons/translators/hpgs/lib/hpgspaintimage.c
Normal 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;
|
||||
}
|
1310
src/add-ons/translators/hpgs/lib/hpgspaintpath.c
Normal file
1310
src/add-ons/translators/hpgs/lib/hpgspaintpath.c
Normal file
File diff suppressed because it is too large
Load Diff
1393
src/add-ons/translators/hpgs/lib/hpgspath.c
Normal file
1393
src/add-ons/translators/hpgs/lib/hpgspath.c
Normal file
File diff suppressed because it is too large
Load Diff
1461
src/add-ons/translators/hpgs/lib/hpgspcl.c
Normal file
1461
src/add-ons/translators/hpgs/lib/hpgspcl.c
Normal file
File diff suppressed because it is too large
Load Diff
290
src/add-ons/translators/hpgs/lib/hpgspe.c
Normal file
290
src/add-ons/translators/hpgs/lib/hpgspe.c
Normal 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;
|
||||
}
|
||||
}
|
||||
}
|
421
src/add-ons/translators/hpgs/lib/hpgspen.c
Normal file
421
src/add-ons/translators/hpgs/lib/hpgspen.c
Normal 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;
|
||||
}
|
||||
|
261
src/add-ons/translators/hpgs/lib/hpgspjl.c
Normal file
261
src/add-ons/translators/hpgs/lib/hpgspjl.c
Normal 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;
|
||||
}
|
87
src/add-ons/translators/hpgs/lib/hpgsplugin.h
Normal file
87
src/add-ons/translators/hpgs/lib/hpgsplugin.h
Normal 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 */
|
1050
src/add-ons/translators/hpgs/lib/hpgsreader.c
Normal file
1050
src/add-ons/translators/hpgs/lib/hpgsreader.c
Normal file
File diff suppressed because it is too large
Load Diff
515
src/add-ons/translators/hpgs/lib/hpgsreader.h
Normal file
515
src/add-ons/translators/hpgs/lib/hpgsreader.h
Normal 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__
|
27560
src/add-ons/translators/hpgs/lib/hpgsrop.c
Normal file
27560
src/add-ons/translators/hpgs/lib/hpgsrop.c
Normal file
File diff suppressed because it is too large
Load Diff
2585
src/add-ons/translators/hpgs/lib/hpgsscanline.c
Normal file
2585
src/add-ons/translators/hpgs/lib/hpgsscanline.c
Normal file
File diff suppressed because it is too large
Load Diff
627
src/add-ons/translators/hpgs/lib/hpgssetup.c
Normal file
627
src/add-ons/translators/hpgs/lib/hpgssetup.c
Normal 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 );
|
||||
}
|
773
src/add-ons/translators/hpgs/lib/hpgstransform.c
Normal file
773
src/add-ons/translators/hpgs/lib/hpgstransform.c
Normal 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);
|
||||
}
|
329
src/add-ons/translators/hpgs/lib/hpgszostream.c
Normal file
329
src/add-ons/translators/hpgs/lib/hpgszostream.c
Normal 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;
|
||||
}
|
Loading…
Reference in New Issue
Block a user