📄 graphics.cxx
字号:
void PCanvasState::SetOrigin(const PPoint & pt)
{
PRect newMap = map;
newMap.SetOrigin(pt);
SetMappingRect(newMap);
}
#endif
//////////////////////////////////////////////////////////////////////////////
// PCanvas
#if defined(_PCANVAS)
inline static long CalculateScaledValue(long value,
int innerOffset, int innerWidth,
int outerOffset, int outerWidth)
{
long tmp = (1000L*(value-innerOffset)*outerWidth)/innerWidth;
if (tmp < 0)
tmp -= 500;
else
tmp += 500;
return tmp/1000L + outerOffset;
}
PDIMENSION PCanvas::FromPixelsDX(PDIMENSION dx) const
{
return (PDIMENSION)CalculateScaledValue(dx,
0, viewport.Width(), 0, map.Width());
}
PDIMENSION PCanvas::FromPixelsDY(PDIMENSION dy) const
{
return (PDIMENSION)CalculateScaledValue(dy,
0, viewport.Height(), 0, map.Height());
}
PORDINATE PCanvas::FromPixelsX(PORDINATE x) const
{
return (PORDINATE)CalculateScaledValue(x,
viewport.X(), viewport.Width(), map.X(), map.Width());
}
PORDINATE PCanvas::FromPixelsY(PORDINATE y) const
{
return (PORDINATE)CalculateScaledValue(y,
viewport.Y(), viewport.Height(), map.Y(), map.Height());
}
PDIMENSION PCanvas::ToPixelsDX(PDIMENSION dx) const
{
return (PDIMENSION)CalculateScaledValue(dx,
0, map.Width(), 0, viewport.Width());
}
PDIMENSION PCanvas::ToPixelsDY(PDIMENSION dy) const
{
return (PDIMENSION)CalculateScaledValue(dy,
0, map.Height(), 0, viewport.Height());
}
PORDINATE PCanvas::ToPixelsX(PORDINATE x) const
{
return (PORDINATE)CalculateScaledValue(x,
map.X(), map.Width(), viewport.X(), viewport.Width());
}
PORDINATE PCanvas::ToPixelsY(PORDINATE y) const
{
return (PORDINATE)CalculateScaledValue(y,
map.Y(), map.Height(), viewport.Y(), viewport.Height());
}
PDIMENSION PCanvas::ToPointsX(PDIMENSION x)
{
long tmp1 = 7200L*x*viewport.Width();
long tmp2 = map.Width()*deviceResX*100L;
if (tmp1 < 0)
tmp1 -= tmp2/2;
else
tmp1 += tmp2/2;
return (PDIMENSION)(tmp1/tmp2);
}
PDIMENSION PCanvas::ToPointsY(PDIMENSION y)
{
long tmp1 = 7200L*y*viewport.Height();
long tmp2 = map.Height()*deviceResY*100L;
if (tmp1 < 0)
tmp1 -= tmp2/2;
else
tmp1 += tmp2/2;
return (PDIMENSION)(tmp1/tmp2);
}
PDIMENSION PCanvas::FromPointsX(PDIMENSION x)
{
long tmp = (100L*x*deviceResX*map.Width())/viewport.Width();
if (tmp < 0)
tmp -= 3600;
else
tmp += 3600;
return (PDIMENSION)(tmp/7200L);
}
PDIMENSION PCanvas::FromPointsY(PDIMENSION y)
{
long tmp = (100L*y*deviceResY*map.Height())/viewport.Height();
if (tmp < 0)
tmp -= 3600;
else
tmp += 3600;
return (PDIMENSION)(tmp/7200L);
}
void PCanvas::DrawBevelledRect(const PRect & rect, BOOL raised, BOOL deep)
{
Save();
PRect bounds = ToPixels(rect);
PDim border = PApplication::Current().GetBorderSize();
SetMappingRect(GetViewportRect());
const PColour & shadowColour = PApplication::Current().GetButtonShadowColour();
const PColour & lightColour = PApplication::Current().GetButtonLightingColour();
const PColour & bkColour = GetFillFgColour();
SetPenFgColour(bkColour);
SetFillFgColour(bkColour);
SetFillBkColour(bkColour);
DrawRect(bounds);
PORDINATE left = bounds.Left();
PORDINATE top = bounds.Top();
PORDINATE right = bounds.Right()-border.Width();
PORDINATE bottom = bounds.Bottom()-border.Height();
if (raised)
SetPenFgColour(shadowColour);
else
SetPenFgColour(lightColour);
SetPenWidth(border.Height());
DrawLine(left, bottom, right+border.Width(), bottom);
bottom -= border.Height();
if (deep)
DrawLine(left+border.Width(), bottom, right+border.Width(), bottom);
SetPenWidth(border.Width());
DrawLine(right, top, right, bottom+border.Height());
right -= border.Width();
if (deep)
DrawLine(right, top+border.Height(), right, bottom+border.Height());
if (raised)
SetPenFgColour(lightColour);
else
SetPenFgColour(shadowColour);
SetPenWidth(border.Width());
DrawLine(left, top, left, bottom+border.Height());
left += border.Width();
if (deep)
DrawLine(left, top, left, bottom);
SetPenWidth(border.Height());
DrawLine(left, top, right+border.Width(), top);
if (deep) {
top += border.Height();
DrawLine(left, top, right, top);
}
Restore();
}
static PString AddEllipses(PCanvas & canvas,
PDIMENSION width, const PString & line, int alignment)
{
int amtTooBig = canvas.MeasureString(line).Width() - width;
if (amtTooBig <= 0)
return line;
PDIMENSION fontWidth = canvas.FromPointsY(canvas.GetFont().GetAvgWidth());
PINDEX numChars = line.GetLength() - (amtTooBig+fontWidth-1)/fontWidth - 5;
PString ellipses, str;
switch (alignment) {
default :
case PCanvas::LeftAlign :
ellipses = " ...";
str = line.Left(numChars) + ellipses;
break;
case PCanvas::RightAlign :
ellipses = "... ";
str = ellipses + line.Right(numChars);
break;
case PCanvas::Centred :
ellipses = " ... ";
str = line.Left((numChars+1)/2) + ellipses + line.Right(numChars/2);
break;
}
while (canvas.MeasureString(str).Width() - width <= 0) {
numChars++;
switch (alignment) {
default :
case PCanvas::LeftAlign :
str = line.Left(numChars) + ellipses;
break;
case PCanvas::RightAlign :
str = ellipses + line.Right(numChars);
break;
case PCanvas::Centred :
str = line.Left((numChars+1)/2) + ellipses + line.Right(numChars/2);
break;
}
}
numChars--;
switch (alignment) {
default :
case PCanvas::LeftAlign :
return line.Left(numChars) + ellipses;
case PCanvas::RightAlign :
return ellipses + line.Right(numChars);
case PCanvas::Centred :
return line.Left((numChars+1)/2) + ellipses + line.Right(numChars/2);
}
}
PDIMENSION PCanvas::DrawString(const PRect & rect, const PString & str, int options)
{
if (GetTextBkColour().GetAlpha() != 0) {
Save();
SetPenStyle(Solid);
SetPenWidth(0);
SetPenMode(SrcCopy);
SetPenFgColour(GetTextBkColour());
SetFillPattern(PPattern());
SetFillMode(SrcCopy);
SetFillFgColour(GetTextBkColour());
DrawRect(rect);
Restore();
}
PDIMENSION spaceWidth = MeasureString(" ").Width();
PStringArray unbrokenLines = str.Lines();
PStringArray lines(unbrokenLines.GetSize());
PINDEX line = 0;
for (PINDEX i = 0; i < unbrokenLines.GetSize(); i++) {
if (MeasureString(unbrokenLines[i]).Width() <= rect.Width())
lines[line++] = unbrokenLines[i];
else {
switch (options&HorizontalWrapMask) {
case NoWrapping :
lines[line++] = unbrokenLines[i];
break;
// break the lines into new lines that are no wider than the rectangle
case WordWrap : {
PString str;
PDIMENSION w = 0;
PStringArray words = unbrokenLines[i].Tokenise(" \t", FALSE);
for (PINDEX k = 0; k < words.GetSize(); k++) {
PDIMENSION x = MeasureString(words[k]).Width();
if (w + x > rect.Width()) {
if (w != 0)
lines[line++] = str;
str = "";
w = 0;
}
else if (w != 0) {
str += " ";
x += spaceWidth;
}
str += words[k];
w += x;
}
lines[line++] = str;
break;
}
// Chop text out of the line so that is no wider than the rectangle
case CentreEllipses :
lines[line++] = AddEllipses(*this,
rect.Width(), unbrokenLines[i], Centred);
break;
case EndEllipses :
lines[line++] = AddEllipses(*this,
rect.Width(), unbrokenLines[i], options&HorizontalAlignmentMask);
break;
}
}
}
PDIMENSION fontHeight = FromPointsY(realFont.GetHeight());
PDIMENSION totalHeight = fontHeight*lines.GetSize();
if (totalHeight > rect.Height()) {
int numLinesToKill = (totalHeight-rect.Height()+fontHeight-1)/fontHeight+1;
int firstLineToKill;
switch (options&VerticalTruncationMask) {
case CentreTruncation :
firstLineToKill = lines.GetSize()/2 - numLinesToKill/2;
break;
case EndTruncation :
switch (options&VerticalAlignmentMask) {
case PCanvas::TopAlign :
firstLineToKill = lines.GetSize() - numLinesToKill;
break;
case PCanvas::CentreVertical :
firstLineToKill = lines.GetSize()/2 - numLinesToKill/2;
break;
default : // BottomAlign and BaseLine
firstLineToKill = 0;
}
break;
default :
firstLineToKill = numLinesToKill = 0;
}
if (numLinesToKill > 0) {
PDIMENSION eWidth = MeasureString(" ... ").Width();
PString s = AddEllipses(*this, rect.Width()/2-eWidth/2,
lines[firstLineToKill], LeftAlign) +
" ... " +
AddEllipses(*this, rect.Width()/2-eWidth/2,
lines[firstLineToKill+numLinesToKill-1], RightAlign);
while (numLinesToKill-- > 0)
lines.RemoveAt(firstLineToKill);
lines.InsertAt(firstLineToKill, new PString(s));
totalHeight = fontHeight*lines.GetSize();
}
}
PORDINATE y;
switch (options&VerticalAlignmentMask) {
case TopAlign :
y = rect.Top();
break;
case CentreVertical :
y = rect.Top() + (rect.Height()-totalHeight)/2;
break;
default : // BottomAlign and BaseLine
y = rect.Bottom() - totalHeight;
}
for (line = 0; line < lines.GetSize(); line++, y += fontHeight) {
switch (options&HorizontalAlignmentMask) {
case LeftAlign :
DrawString(rect.Left(), y, lines[line], LeftAlign);
break;
case RightAlign :
DrawString(rect.Right(), y, lines[line], RightAlign);
break;
case Centred :
DrawString((rect.Left()+rect.Right())/2, y, lines[line], Centred);
break;
case Justified :
// Split the line into space separated words
PStringArray words = lines[line].Tokenise(" ", FALSE);
if (words.GetSize() <= 1)
DrawString(rect.Left(), y, lines[line], LeftAlign);
else {
// Now get the width inpixesl of each word
PWORDArray wordWidths(words.GetSize());
PDIMENSION totalWidth = 0;
PINDEX word;
for (word = 0; word < words.GetSize(); word++) {
wordWidths[word] = (WORD)MeasureString(words[word]).Width();
totalWidth += wordWidths[word];
}
if (rect.Width() <= totalWidth)
DrawString(rect.Left(), y, lines[line], LeftAlign);
else {
// Now calculate the size of each space
PORDINATE spaceWidth = (rect.Width()-totalWidth)/(words.GetSize()-1);
// Finally, output each word at x location determined by space width
PORDINATE x = rect.Left();
for (word = 0; word < words.GetSize(); word++) {
DrawString(x, y, words[word], LeftAlign);
x += wordWidths[word] + spaceWidth;
}
}
}
}
}
return lines.GetSize()*fontHeight;
}
PDIMENSION PCanvas::MeasureString(const PString & str, PDIMENSION width)
{
PStringArray lines = str.Lines();
PDIMENSION height = 0;
for (PINDEX line = 0; line < lines.GetSize(); line++) {
PDim lineDim(MeasureString(lines[line]));
if (lineDim.Width() > width) {
}
height += lineDim.Height();
}
return height;
}
void PCanvas::Restore()
{
State * old = stack.Pop();
SetPenStyle(old->GetPenStyle());
SetPenWidth(old->GetPenWidth());
SetPenMode(old->GetPenMode());
SetPenFgColour(old->GetPenFgColour());
SetPenBkColour(old->GetPenBkColour());
SetFillFgColour(old->GetFillFgColour());
SetFillBkColour(old->GetFillBkColour());
SetFillPattern(old->GetFillPattern());
SetFillMode(old->GetFillMode());
SetFont(old->font);
SetTextFgColour(old->GetTextFgColour());
SetTextBkColour(old->GetTextBkColour());
SetPalette(old->GetPalette());
SetPolyFillMode(old->GetPolyFillMode());
SetViewportRect(old->GetViewportRect());
SetMappingRect(old->GetMappingRect());
delete old;
}
#endif
//////////////////////////////////////////////////////////////////////////////
// PInteractorCanvas
#if defined(_PINTERACTORCANVAS)
void PInteractorCanvas::Construct(BOOL inPixels)
{
PCanvasState::SetMappingRect(PRect(0, 0, 100, 100));
if (inPixels)
PCanvasState::SetViewportRect(map);
else
PCanvasState::SetViewportRect(PRect(0, 0,
(PDIMENSION)interactor->ToPixelsX(100),
(PDIMENSION)interactor->ToPixelsY(100)));
const PColour & fgColour = interactor->GetForegroundColour();
const PColour & bkColour = interactor->GetBackgroundColour();
PCanvasState::SetPenFgColour(fgColour);
PCanvasState::SetPenBkColour(bkColour);
PCanvasState::SetFillFgColour(bkColour);
PCanvasState::SetFillBkColour(fgColour);
PCanvasState::SetTextFgColour(fgColour);
PCanvasState::SetTextBkColour(bkColour);
PCanvasState::SetFont(interactor->GetFont());
}
void PInteractorCanvas::Scroll(PORDINATE dx, PORDINATE dy)
{
Scroll(dx, dy, GetDrawingBounds());
}
void PInteractorCanvas::Scroll(const PPoint & amt)
{
Scroll(amt.X(), amt.Y(), GetDrawingBounds());
}
void PInteractorCanvas::Scroll(const PPoint & amt, const PRect & rect)
{
Scroll(amt.X(), amt.Y(), rect);
}
#endif
//////////////////////////////////////////////////////////////////////////////
// PMemoryCanvas
PRect PMemoryCanvas::GetDrawingBounds() const
{
return FromPixels(PRect(0, 0, image->Width(), image->Height()));
}
#undef new
// End Of File ///////////////////////////////////////////////////////////////
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -