summaryrefslogtreecommitdiffstats
path: root/kbarcode/gnubarcode.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'kbarcode/gnubarcode.cpp')
-rw-r--r--kbarcode/gnubarcode.cpp348
1 files changed, 348 insertions, 0 deletions
diff --git a/kbarcode/gnubarcode.cpp b/kbarcode/gnubarcode.cpp
new file mode 100644
index 0000000..6f69644
--- /dev/null
+++ b/kbarcode/gnubarcode.cpp
@@ -0,0 +1,348 @@
+/***************************************************************************
+ gnubarcode.cpp - description
+ -------------------
+ begin :
+ copyright : (C) 2005 by Dominik Seichter
+ email : domseichter@web.de
+ ***************************************************************************/
+
+/***************************************************************************
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ ***************************************************************************/
+
+#include "gnubarcode.h"
+
+#ifdef _ENABLE_NATIVE_GNU_BARCODE
+
+#include <barcode.h>
+#include "barkode.h"
+#include <string.h>
+#include <ctype.h>
+
+#include <qfont.h>
+#include <qpainter.h>
+#include <qpaintdevicemetrics.h>
+
+#include <klocale.h>
+
+#define FONT_SPACE (2*m_scaley)
+#define SHRINK_AMOUNT 0.15
+#define MUL_FACTOR 10
+
+GnuBarcode::GnuBarcode()
+ : BarkodeEngine()
+{
+ m_item = NULL;
+ m_size = QSize( 0, 0 );
+
+ m_scalex = 1.0;
+ m_scaley = 1.0;
+
+ m_font_size = 10;
+}
+
+GnuBarcode::~GnuBarcode()
+{
+ if( m_item )
+ Barcode_Delete( m_item );
+}
+
+void GnuBarcode::update( const QPaintDevice* device )
+{
+ QString val = barkode->parsedValue();
+ m_valid = false;
+
+ if( m_item )
+ {
+ qDebug("Deleting");
+ Barcode_Delete( m_item );
+ m_item = NULL;
+ }
+
+ if( val.isEmpty() )
+ return;
+
+ char* value = new char[val.length()+1];
+ strncpy( value, val.latin1(), val.length()+1 );
+ value[val.length()] = '\0';
+
+ m_item = Barcode_Create( value );
+ if( !m_item )
+ {
+ Barcode_Delete( m_item );
+ m_item = NULL;
+ delete [] value;
+ return;
+ }
+
+ if( Barcode_Encode( m_item, Barkode::internalType( barkode->type() ) ) == -1 )
+ {
+ Barcode_Delete( m_item );
+ m_item = NULL;
+
+ delete [] value;
+ return;
+ }
+
+ delete [] value;
+
+ QPaintDeviceMetrics metrics( device );
+ m_scalex = (double)metrics.logicalDpiX() / (double)QPaintDevice::x11AppDpiX();
+ m_scaley = (double)metrics.logicalDpiY() / (double)QPaintDevice::x11AppDpiY();
+
+ // 72.0 is the postscript resolution generated by GNU barcode
+ m_scale_ps_x = (double)metrics.logicalDpiX() / 72.0;
+ m_scale_ps_y = (double)metrics.logicalDpiY() / 72.0;
+
+/* m_scalex *= m_scale_ps_x;
+ m_scaley *= m_scale_ps_y;*/
+
+ m_font_size = (int)(barkode->fontsize() * barkode->scaling() * m_scaley);
+ setupSize();
+ m_valid = true;
+}
+
+const QSize GnuBarcode::size() const
+{
+ if( m_size.isNull() )
+ return QSize( 100, 80 );
+ else
+ return m_size;
+}
+
+void GnuBarcode::drawBarcode( QPainter & painter, int x, int y )
+{
+ int dx = x + barkode->quietZone();
+ int dy = y + barkode->quietZone();
+
+ if( !m_item )
+ {
+ barkode->drawInvalid( painter, x, y );
+ return;
+ }
+
+ painter.save();
+ painter.scale( m_scalex, m_scaley );
+
+ // based on David J. Humphreys barcode-svg
+ // Draw the bars
+ drawBars( &painter, (int)(dx/m_scalex), (int)(dy/m_scaley) );
+
+ // Only scale for the bars, text should be scaled
+ // correctly by Qt on Qt >= 3.3.2
+ painter.restore();
+
+ // draw the text
+ if( barkode->textVisible() )
+ drawText( &painter, dx, dy );
+}
+
+void GnuBarcode::setupSize()
+{
+ m_bar_height = (int)(barkode->barHeight() * barkode->scaling() * barkode->cut());
+ m_barcode_height = m_bar_height;
+ if( barkode->textVisible() )
+ m_barcode_height += (int)(m_font_size/2 + FONT_SPACE*2);
+
+ unsigned int width = drawBars( 0 , 0, 0 );
+ unsigned int twidth = drawText( 0, 0, 0 );
+
+ //if(m_item->height == 0)
+ m_item->height = m_barcode_height + (2 * barkode->quietZone());
+
+ width = ( width > twidth ? width : twidth );
+ width += 2* barkode->quietZone();
+
+ //if(m_item->width == 0)
+ m_item->width = width;
+
+ m_size.setWidth( (int)(m_item->width * m_scalex) );
+ m_size.setHeight( (int)(m_item->height * m_scaley) );
+}
+
+int GnuBarcode::drawBars( QPainter* painter, int x, int y )
+{
+#if 0
+ int height = 0; // height of the bar to draw
+ int xpos = 0; // Where the current box is drawn
+ int current = 0;
+ unsigned int i = 0;
+
+ qDebug("Partial=%s\n", m_item->partial );
+ for( i = 0; i < strlen(m_item->partial); i++)
+ {
+ current = (int)m_item->partial[i] - ASCII_ZERO;
+ /* Guide bar */
+ if(current > 9)
+ {
+ height = m_barcode_height;
+ current = (int)m_item->partial[++i] - ASCII_ZERO;
+ i++; /* Skip the following 'a' */
+ }
+ else
+ height = m_bar_height;
+
+ current *= barkode->scaling();
+
+ if( current < 0 )
+ {
+ qDebug("current < 0: %i", current );
+ current = 0;
+ break;
+ }
+
+ if( i % 2)
+ {
+ painter.fillRect( x + xpos, y, current, height, barkode->foreground() );
+ }
+
+ xpos += current;
+ }
+#endif
+ int xpos;
+ int mode = '-'; // text below bars
+ char *ptr;
+ int i, j;
+ int x0, yr, y0;
+
+ xpos = m_item->partial[0]-'0';
+
+ for (ptr = m_item->partial+1, i=1; *ptr; ptr++, i++)
+ {
+ /* special cases: '+' and '-' */
+ if (*ptr == '+' || *ptr == '-')
+ {
+ mode = *ptr; /* don't count it */ i++; continue;
+ }
+ /* j is the width of this bar/space */
+ if (isdigit (*ptr))
+ j = *ptr-'0';
+ else
+ j = *ptr-'a'+1;
+
+ j = (int)( j * barkode->scaling() );
+ if (i%2)
+ {
+ x0 = xpos + j/2;
+ y0 = y;
+ yr = m_barcode_height;
+
+ if( barkode->textVisible() )
+ {
+ // leave space for text
+ if (mode == '-')
+ {
+ // text below bars
+ if( isdigit( *ptr ) )
+ yr = m_bar_height;
+ else
+ yr = m_barcode_height;
+ } else { /* '+' */
+ // text above bars
+ // TODO: this needs testing and a GUI
+ if( isdigit( *ptr ) )
+ yr = m_bar_height;
+ else
+ {
+ yr = m_barcode_height;
+ y0 += (m_barcode_height - m_bar_height);
+ }
+ }
+ }
+
+ if( painter )
+ {
+ painter->fillRect( x + x0, y0, j, yr, barkode->foreground() );
+ }
+ //qDebug("Bar = %i", j );
+ }
+ xpos += j;
+ }
+
+ return xpos;
+}
+
+int GnuBarcode::drawText( QPainter* painter, int x, int y )
+{
+#if 0
+ unsigned int infosz = strlen( m_item->textinfo );
+ unsigned int correction = 0; // This correction seems to be needed to align text properly
+ unsigned int j = 0;
+ unsigned int i = 0;
+ int prev_x = 0;
+ int xpos = 0;
+
+ double dub1, fsize;
+ char printer;
+ char *temp_info = new char[infosz+1];
+
+ painter.setFont( QFont( "Helvetica", 12 ) );
+ while(i < infosz)
+ {
+ for(j = 0; m_item->textinfo[i + j + 1] != ' ' &&
+ m_item->textinfo[i + j + 1] != '\0';j++); /* Empty loop, just increment j */
+ j ++;
+ strncpy(temp_info, (m_item->textinfo + i),j);
+ sscanf(temp_info, "%lf:%lf:%c", &dub1, &fsize, &printer);
+ i += j;
+
+ xpos = (int)dub1;
+ //if((xpos - prev_x) >= 10)
+ //correction += 2;
+
+ prev_x = xpos;
+ painter.drawText( x + ((xpos-correction) * m_scalex),
+ y + ((m_bar_height + (unsigned int)(barkode->fontsize()/ 2) + FONT_SPACE) * m_scaley),
+ QChar( printer ) );
+ }
+ delete [] temp_info;
+#endif
+
+ double f1, f2;
+ int y0;
+ char* ptr;
+ char c;
+
+ int mode = '-';
+ for (ptr = m_item->textinfo; ptr; ptr = strchr(ptr, ' '))
+ {
+ while (*ptr == ' ')
+ ptr++;
+ if (!*ptr)
+ break;
+ if (*ptr == '+' || *ptr == '-')
+ {
+ mode = *ptr; continue;
+ }
+
+ if (sscanf(ptr, "%lf:%lf:%c", &f1, &f2, &c) != 3)
+ {
+ fprintf(stderr, "barcode: impossible data: %s\n", ptr);
+ continue;
+ }
+
+ if( mode == '-' )
+ {
+ // text below bars
+ y0 = y + (int)(m_bar_height * m_scaley + m_font_size - FONT_SPACE);
+ }
+ else
+ y0 = (int)(y + FONT_SPACE);
+
+ if( painter )
+ {
+ painter->setFont( QFont( "Helvetica", m_font_size ) );
+ painter->drawText( x + (int)(f1 * m_scalex * barkode->scaling() ), y0, QChar( c ) );
+ }
+ }
+
+ return x;
+}
+
+#endif // _ENABLE_NATIVE_GNU_BARCODE
+