You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

480 lines
11 KiB

/*
* Copyright (C) 2000-2001 theKompany.com & Dave Marotti
*
* 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.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#include "qsruler.h"
#include <stdlib.h>
#include <math.h>
//------------------------------------------------------------//
/*
* Functions for converting
* Point <-> Inch <-> Millimeter<-> Pica <-> Centimetre <-> Didot <-> Cicero
* 1 Inch = 72 pt = 6 pica = 25.4 mm = 67.54151050 dd = 5.628459208 cc
*/
float cvtPtToMm(float value)
{
return 25.4 * value / 72.0;
}
//------------------------------------------------------------//
float cvtPtToCm(float value)
{
return 2.54 * value / 72.0;
}
//------------------------------------------------------------//
float cvtPtToPica(float value)
{
return value / 12.0;
}
//------------------------------------------------------------//
float cvtPicaToPt(float value)
{
return value * 12.0;
}
//------------------------------------------------------------//
float cvtPtToInch(float value)
{
return value / 72.0;
}
//------------------------------------------------------------//
float cvtPtToDidot(float value)
{
return value * 1238.0 / 1157.0; // 1157 dd = 1238 pt
}
//------------------------------------------------------------//
float cvtPtToCicero(float value)
{
return value * 1238.0 / (1157.0 * 12.0); // 1 cc = 12 dd
}
//------------------------------------------------------------//
float cvtInchToPt(float value)
{
return value * 72.0;
}
//------------------------------------------------------------//
float cvtMmToPt(float value)
{
return value / 25.4 * 72.0;
}
//------------------------------------------------------------//
float cvtCmToPt(float value)
{
return value / 2.54 * 72.0;
}
//------------------------------------------------------------//
float cvtDidotToPt(float value)
{
return value * 1157.0 / 1238.0;
}
//------------------------------------------------------------//
float cvtCiceroToPt(float value)
{
return value * (1157.0 * 12.0) / 1238.0;
}
//------------------------------------------------------------//
float cvtPtToUnit(int unit, float value)
{
switch (unit) {
case UnitMillimeter:
return cvtPtToMm (value);
break;
case UnitPica:
return cvtPtToPica (value);
break;
case UnitInch:
return cvtPtToInch (value);
break;
case UnitCentimeter:
return cvtPtToCm (value);
break;
case UnitDidot:
return cvtPtToDidot (value);
break;
case UnitCicero:
return cvtPtToCicero (value);
break;
default:
return value;
}
}
//------------------------------------------------------------//
float cvtUnitToPt(int unit, float value)
{
switch (unit) {
case UnitMillimeter:
return cvtMmToPt (value);
break;
case UnitInch:
return cvtInchToPt (value);
break;
case UnitCentimeter:
return cvtCmToPt (value);
break;
case UnitDidot:
return cvtDidotToPt (value);
break;
case UnitPica:
return cvtPicaToPt (value);
break;
case UnitCicero:
return cvtCiceroToPt (value);
break;
default:
return value;
}
}
//------------------------------------------------------------//
#define MARKER_WIDTH 1
#define MARKER_HEIGHT 20
#define RULER_SIZE 20
QSRuler::QSRuler(Orientation o, QWidget *parent, const char *name)
: QFrame(parent, name, WRepaintNoErase | WResizeNoErase )
{
setBackgroundMode(NoBackground);
setFrameStyle(Box | Sunken/*Raised*/);
setLineWidth(1);
setMidLineWidth(0);
orientation = o;
munit = UnitPoint;
m_pZoom = 1.0;
firstVisible = 0;
buffer = 0L;
currentPosition = -1;
if (orientation == Horizontal) {
setFixedHeight(RULER_SIZE);
initMarker(MARKER_WIDTH, MARKER_HEIGHT);
} else {
setFixedWidth(RULER_SIZE);
initMarker(MARKER_HEIGHT, MARKER_WIDTH);
}
const char* nums[] = {
"70 7 2 1",
" c Black",
"X c None",
"XX XXXXXX XXXX XXXX XXXXXX XXX XXXX XXX XXX XXXX XX",
"X XXX XXXX XXX XXX XX XXX XXXX XXX XXXXXXX XXXXXXXXX XX XXX XX XXX X",
"X XXX XXXXX XXXXXXX XXXXXX XXX X XXX XXXXXX XXXXXXXXX XXX XXX XX XXX X",
"X XXX XXXXX XXXXX XXXXX XXX XX XXX XXX XXXXXX XXXX XXXX X",
"X XXX XXXXX XXXX XXXXXXXXX XX XXXXXX XX XXX XXXX XXXX XXX XXXXXX X",
"X XXX XXXXX XXX XXXXXX XXX XXXXX XXXXXXX XX XXX XXXX XXXX XXX XXXXX XX",
"XX XXXXXX XXX XXX XXXXXX XXX XXXX XXXXX XXXXX XXXX XXX"
};
m_pNums = new QPixmap(nums);
}
QSRuler::~QSRuler()
{
if (buffer)
delete buffer;
delete marker;
delete m_pNums;
}
void QSRuler::initMarker(int w, int h)
{
QPainter p;
marker = new QPixmap(w,h);
p.begin(marker);
p.setPen(blue);
p.eraseRect(0, 0, w, h);
p.drawLine(0,0,w-1,h-1);
p.end();
}
void QSRuler::recalculateSize(QResizeEvent*)
{
if (buffer) {
delete buffer;
buffer = 0L;
}
int w, h;
if (orientation == Horizontal) {
w = width();
h = RULER_SIZE;
} else {
w = RULER_SIZE;
h = height();
}
buffer = new QPixmap(w, h);
drawQSRuler();
updatePointer(currentPosition,currentPosition);
}
int QSRuler::unit()
{
return munit;
}
void QSRuler::setUnit(int u)
{
munit = u;
drawQSRuler();
updatePointer(currentPosition,currentPosition);
repaint();
}
void QSRuler::setZoom(float zoom)
{
if ( m_pZoom != zoom ) {
m_pZoom = zoom;
recalculateSize(0L);
//drawQSRuler();
update();
//updatePointer(currentPosition, currentPosition);
//repaint();
}
}
void QSRuler::updatePointer(int x, int y )
{
if (! buffer)
return;
if (orientation == Horizontal) {
if (currentPosition != -1) {
repaint(QRect(currentPosition, 1, MARKER_WIDTH, MARKER_HEIGHT));
}
if (x != -1) {
bitBlt(this, x, 1, marker, 0, 0, MARKER_WIDTH, MARKER_HEIGHT);
currentPosition = x;
}
} else {
if (currentPosition != -1) {
repaint(QRect (1, currentPosition, MARKER_HEIGHT, MARKER_WIDTH));
}
if (y != -1) {
bitBlt(this, 1, y, marker, 0, 0, MARKER_HEIGHT, MARKER_WIDTH);
currentPosition = y;
}
}
}
void QSRuler::updateVisibleArea( int xpos, int ypos )
{
if (orientation == Horizontal && firstVisible != xpos ) {
firstVisible = xpos;
drawQSRuler();
//repaint();
update();
}
else
if (orientation == Vertical && firstVisible != ypos ) {
firstVisible = ypos;
drawQSRuler();
update(); //repaint();
}
}
void QSRuler::paintEvent( QPaintEvent* e )
{
if (!buffer)
return;
const QRect& rect = e->rect();
if (orientation == Horizontal) {
bitBlt(this, rect.topLeft(), buffer, rect);
} else {
bitBlt(this, rect.topLeft(), buffer, rect);
}
QFrame::paintEvent(e);
}
void QSRuler::drawQSRuler()
{
QPainter p;
QString buf;
int st1 = 0;
int st2 = 0;
int st3 = 0;
int st4 = 0;
int stt = 0;
if (!buffer)
return;
p.begin(buffer);
p.setPen(QColor(0x70,0x70,0x70));
p.setBackgroundColor(colorGroup().background());
p.eraseRect(0, 0, buffer->width(), buffer->height());
switch (munit) {
case UnitPoint:
case UnitMillimeter:
case UnitDidot:
case UnitCicero:
st1 = 1;
st2 = 5;
st3 = 10;
st4 = 25;
stt = 5;
break;
case UnitCentimeter:
case UnitPica:
case UnitInch:
st1 = 1;
st2 = 2;
st3 = 5;
st4 = 10;
stt = 1;
break;
default:
break;
}
if (orientation == Horizontal) {
int pos = 0;
bool s1 = cvtUnitToPt(munit,st1)*m_pZoom > 3.0;
bool s2 = cvtUnitToPt(munit,st2)*m_pZoom > 3.0;
bool s3 = cvtUnitToPt(munit,st3)*m_pZoom > 3.0;
bool s4 = cvtUnitToPt(munit,st4)*m_pZoom > 3.0;
float cx = cvtPtToUnit(munit,7*4)/m_pZoom;
int step = ((int)(cx/(float)stt)+1)*stt;
int start = (int)(cvtPtToUnit(munit,firstVisible)/m_pZoom);
do {
pos = (int)(cvtUnitToPt(munit,start)*m_pZoom - firstVisible);
if ( !s3 && s4 && start % st4 == 0 )
p.drawLine(pos,RULER_SIZE-9,pos,RULER_SIZE);
if ( s3 && start % st3 == 0 )
p.drawLine(pos,RULER_SIZE-9,pos,RULER_SIZE);
if ( s2 && start % st2 == 0 )
p.drawLine(pos,RULER_SIZE-7,pos,RULER_SIZE);
if ( s1 && start % st1 == 0 )
p.drawLine(pos,RULER_SIZE-5,pos,RULER_SIZE);
if ( start % step == 0 ) {
buf.setNum(abs(start));
drawNums(&p,pos,4,buf,true);
}
start++;
} while (pos < buffer->width());
} else {
int pos = 0;
bool s1 = cvtUnitToPt(munit,st1)*m_pZoom > 3.0;
bool s2 = cvtUnitToPt(munit,st2)*m_pZoom > 3.0;
bool s3 = cvtUnitToPt(munit,st3)*m_pZoom > 3.0;
bool s4 = cvtUnitToPt(munit,st4)*m_pZoom > 3.0;
float cx = cvtPtToUnit(munit,8*4)/m_pZoom;
int step = ((int)(cx/(float)stt)+1)*stt;
int start = (int)(cvtPtToUnit(munit,firstVisible)/m_pZoom);
do {
pos = (int)(cvtUnitToPt(munit,start)*m_pZoom - firstVisible);
if ( !s3 && s4 && start % st4 == 0 )
p.drawLine(RULER_SIZE-9,pos,RULER_SIZE,pos);
if ( s3 && start % st3 == 0 )
p.drawLine(RULER_SIZE-9,pos,RULER_SIZE,pos);
if ( s2 && start % st2 == 0 )
p.drawLine(RULER_SIZE-7,pos,RULER_SIZE,pos);
if ( s1 && start % st1 == 0 )
p.drawLine(RULER_SIZE-5,pos,RULER_SIZE,pos);
if ( start % step == 0 ) {
buf.setNum(abs(start));
drawNums(&p,4,pos,buf,false);
}
start++;
} while (pos < buffer->height());
}
p.end();
}
void QSRuler::resizeEvent(QResizeEvent* e)
{
recalculateSize(e);
}
void QSRuler::show()
{
if (orientation == Horizontal) {
setFixedHeight(RULER_SIZE);
initMarker(MARKER_WIDTH,MARKER_HEIGHT);
} else {
setFixedWidth(RULER_SIZE);
initMarker(MARKER_HEIGHT,MARKER_WIDTH);
}
QWidget::show();
}
void QSRuler::hide()
{
if (orientation == Horizontal)
setFixedHeight(1);
else
setFixedWidth(1);
}
void QSRuler::drawNums(QPainter* p, int x, int y, QString& num, bool orientationHoriz)
{
if (orientationHoriz)
x -= 7;
else
y -= 8;
for ( uint k = 0; k < num.length(); k++ ) {
int st = num.at(k).digitValue()*7;
p->drawPixmap(x,y,*m_pNums,st,0,7,7);
if (orientationHoriz)
x += 7;
else
y += 8;
}
}