home *** CD-ROM | disk | FTP | other *** search
Text File | 1996-09-17 | 48.9 KB | 1,881 lines | [TEXT/MPS ] |
- //========================================================================================
- //
- // File: SLRender.cpp
- // Release Version: $ ODF 2 $
- //
- // Copyright: (c) 1993 - 1996 by Apple Computer, Inc., all rights reserved.
- //
- //========================================================================================
-
- #include "FWOS.hpp"
-
- #ifndef SLRENDER_H
- #include "SLRender.h"
- #endif
-
- #ifndef PRGDEV_H
- #include "PRGDev.h"
- #endif
-
- #ifndef PRTXTBUF_H
- #include "PRTxtBuf.h"
- #endif
-
- #ifndef SLGC_H
- #include "SLGC.h"
- #endif
-
- #ifndef FWRECT_H
- #include "FWRect.h"
- #endif
-
- #ifndef PRMDASH_H
- #include "PRMDash.h"
- #endif
-
- #ifndef FWODGEOM_H
- #include "FWODGeom.h"
- #endif
-
- #ifndef FWSTYLE_H
- #include "FWStyle.h"
- #endif
-
- #ifndef PRPOLY_H
- #include "PRPoly.h"
- #endif
-
- #ifndef SLGRGLOB_H
- #include "SLGrGlob.h"
- #endif
-
- #ifndef PRPICTUR_H
- #include "PRPictur.h"
- #endif
-
- #ifndef PRBITMAP_H
- #include "PRBitmap.h"
- #endif
-
- #ifndef FWGRUTIL_H
- #include "FWGrUtil.h"
- #endif
-
- #ifndef PRGRUTIL_H
- #include "PRGrUtil.h"
- #endif
-
- #ifndef PRICON_H
- #include "PRIcon.h"
- #endif
-
- #ifndef FWMEMMGR_H
- #include "FWMemMgr.h"
- #endif
-
- #if defined(FW_BUILD_MAC) && !defined(__ICONS__)
- #include <Icons.h>
- #endif
-
- #ifndef SLREGION_H
- #include "SLRegion.h"
- #endif
-
- #ifdef FW_BUILD_MAC
- #pragma segment FWGraphx_Render
- #endif
-
- //========================================================================================
- // Local helpers
- //========================================================================================
-
- // All static method can fail
- static FW_PlatformCoordinate PrivTextBox(Environment* ev,
- FW_CPrivGraphicsDevice* device,
- FW_CPrivTextBuffer *textBuffer,
- const FW_CPlatformRect& box,
- FW_TextBoxOptions options,
- FW_Boolean draw,
- FW_HFont font);
-
- static void PrivRenderTextBuffer(Environment* ev,
- FW_SGraphicContext& gc,
- FW_CPrivTextBuffer* textBuffer,
- const FW_SPoint& position,
- FW_TextAlignment textAlignment,
- FW_ERenderVerbs renderVerb,
- FW_HInk ink,
- FW_HFont font);
-
- static FW_Fixed PrivRenderTextBoxBuffer(Environment* ev,
- FW_SGraphicContext& gc,
- FW_CPrivTextBuffer* textBuffer,
- const FW_SRect& box,
- FW_TextBoxOptions options,
- FW_ERenderVerbs renderVerb,
- FW_HInk ink,
- FW_HFont font);
-
- static void PrivTextBoxSizeBuffer(Environment* ev,
- FW_SGraphicContext& gc,
- FW_CPrivTextBuffer *textBuffer,
- FW_HFont font,
- FW_TextBoxOptions options,
- FW_SRect& textBox);
-
- static void PrivTextExtentBuffer(Environment* ev,
- FW_SGraphicContext& gc,
- FW_CPrivTextBuffer* textBuffer,
- FW_HFont font,
- FW_SPoint& textExtent);
-
- #ifdef FW_BUILD_MAC
-
- static void MacSelectInkAndStyle(
- FW_CPrivGraphicsDevice* device,
- FW_EPrivShapeCategories shapeCategory,
- FW_ERenderVerbs renderVerb,
- FW_HInk ink,
- FW_HStyle style,
- FW_Boolean& styleIsDash,
- FW_Boolean& styleIsHairline);
-
- static FW_CPlatformPoint MacCalcTextPosition(
- FW_CPrivGraphicsDevice* device,
- short byteCount, const char* text,
- FW_TextAlignment textAlignment,
- const FW_CPlatformPoint& position);
-
- static void MacStrikeOut(
- FW_CPrivGraphicsDevice* device,
- short beforePosX,
- short beforePosY);
-
- //----------------------------------------------------------------------------------------
- // FW_PrivSelectHairline -- a Mac utility class for using the SetLineWidth picComment
- //----------------------------------------------------------------------------------------
-
- class FW_PrivSelectHairline
- {
- public:
- FW_DECLARE_AUTO(FW_PrivSelectHairline)
-
- FW_PrivSelectHairline(FW_Boolean setHairline);
- ~FW_PrivSelectHairline();
-
- private:
-
- enum { eSetLineWidthPicComment = 182 };
-
- FW_PlatformHandle fData;
- };
-
- #endif
-
- //========================================================================================
- // Local macros to make rendering code more straightforward
- //========================================================================================
-
- #ifdef FW_BUILD_WIN
-
- #define FW_CHECK_RENDER \
- FW_ASSERT(&gc == FW_PrivGC_GetCurrent(ev));
-
- #endif
-
- #ifdef FW_BUILD_MAC
-
- #define FW_CHECK_RENDER \
- FW_ASSERT(&gc == FW_PrivGC_GetCurrent(ev)); \
- FW_ASSERT(gc.fGraphicDevice->GetPlatformCanvas() == FW_QDGlobals.thePort);
-
- #endif
-
- #define FW_CHECK_RENDER_VERB \
- if (renderVerb == FW_kNoRendering) \
- return;
-
- #define FW_RENDER_PROLOG \
- FW_CHECK_RENDER \
- FW_CPrivGraphicsDevice* device = gc.fGraphicDevice;
-
- #define FW_CHECK_INK \
- FW_ASSERT(ink != NULL);
-
- #define FW_CHECK_STYLE \
- FW_ASSERT(style != NULL);
-
- #define FW_CHECK_FONT \
- FW_ASSERT(font != NULL);
-
- //========================================================================================
- // Rendering APIs
- //========================================================================================
-
- //----------------------------------------------------------------------------------------
- // FW_PrivRenderRect
- //----------------------------------------------------------------------------------------
-
- void SL_API FW_PrivRenderRect(Environment* ev,
- FW_SGraphicContext& gc,
- const FW_SRect& rect,
- FW_ERenderVerbs renderVerb,
- FW_HInk ink,
- FW_HStyle style)
- {
- FW_RENDER_PROLOG
- FW_CHECK_RENDER_VERB
- FW_CHECK_INK
- FW_CHECK_STYLE
-
- FW_SOM_TRY
- {
- FW_CPlatformRect plfmRect;
- FW_PrivGC_LogicalToDeviceRect(ev, gc, rect, plfmRect);
- FW_FailOnEvError(ev);
-
- #ifdef FW_BUILD_WIN
- FW_Boolean frameBrush = device->SelectInkAndStyle(ink, style,
- FW_kGeometricShapeWithInvert,
- renderVerb);
-
- HDC hDC = *device;
- if (frameBrush)
- {
- int penSizeX = device->fPenSize.x;
- int penSizeY = device->fPenSize.y;
-
- device->fGDIBrush.SelectObject(hDC);
- ::PatBlt(hDC, plfmRect.left, plfmRect.top, plfmRect.right - plfmRect.left, penSizeY, PATCOPY);
- ::PatBlt(hDC, plfmRect.right - penSizeX, plfmRect.top, penSizeX, plfmRect.bottom - plfmRect.top, PATCOPY);
- ::PatBlt(hDC, plfmRect.left, plfmRect.top, penSizeX, plfmRect.bottom - plfmRect.top, PATCOPY);
- ::PatBlt(hDC, plfmRect.left, plfmRect.bottom - penSizeY, plfmRect.right - plfmRect.left, penSizeY, PATCOPY);
- }
- else
- {
- if (ink->GetTransferMode() == FW_kInvert || ink->GetTransferMode() == FW_kHilite || || ink->GetTransferMode() == FW_kSystemHilite)
- {
- ::InvertRect(hDC, &plfmRect);
- }
- else
- {
- if (renderVerb == FW_kFill)
- {
- plfmRect.right++;
- plfmRect.bottom++;
- }
-
- ::Rectangle(hDC, plfmRect.left, plfmRect.top, plfmRect.right, plfmRect.bottom);
- }
- }
- #endif
- #ifdef FW_BUILD_MAC
- FW_Boolean styleIsDash;
- FW_Boolean styleIsHairline;
- MacSelectInkAndStyle(device, FW_kGeometricShape, renderVerb, ink, style, styleIsDash, styleIsHairline);
-
- if (renderVerb == FW_kFrame)
- {
- FW_PrivSelectHairline hairSelector(styleIsHairline && !device->GetODCanvas()->IsDynamic(ev));
-
- if (styleIsDash)
- {
- FW_CPrivMacDashDraw draw(style->GetDashStyle());
-
- ::MoveTo(plfmRect.left, plfmRect.top);
- draw.LineTo(plfmRect.right - 1, plfmRect.top);
- draw.LineTo(plfmRect.right - 1, plfmRect.bottom - 1);
- draw.LineTo(plfmRect.left, plfmRect.bottom - 1);
- draw.LineTo(plfmRect.left, plfmRect.top);
- }
- else
- {
- ::FrameRect(&plfmRect);
- }
- }
- else
- {
- switch (ink->GetTransferMode())
- {
- case FW_kErase:
- ::EraseRect(&plfmRect);
- break;
-
- case FW_kInvert:
- ::InvertRect(&plfmRect);
- break;
-
- default:
- ::PaintRect(&plfmRect);
- }
- }
- #endif
- }
- FW_SOM_CATCH
- }
-
- //----------------------------------------------------------------------------------------
- // FW_PrivRenderOval
- //----------------------------------------------------------------------------------------
-
- void SL_API FW_PrivRenderOval(Environment* ev,
- FW_SGraphicContext& gc,
- const FW_SRect& rect,
- FW_ERenderVerbs renderVerb,
- FW_HInk ink,
- FW_HStyle style)
- {
- FW_RENDER_PROLOG
- FW_CHECK_RENDER_VERB
- FW_CHECK_INK
- FW_CHECK_STYLE
-
- FW_SOM_TRY
- {
- FW_CPlatformRect plfmRect;
- FW_PrivGC_LogicalToDeviceRect(ev, gc, rect, plfmRect);
- FW_FailOnEvError(ev);
-
- #ifdef FW_BUILD_WIN
- FW_Boolean frameBrush = device->SelectInkAndStyle(ink, style, FW_kGeometricShape, renderVerb);
-
- if (frameBrush)
- {
- HRGN hrgn = ::CreateEllipticRgn(plfmRect.left, plfmRect.top, plfmRect.right + 1, plfmRect.bottom + 1);
- ::FrameRgn(*device, hrgn, device->fGDIBrush.GetBrush(*device), device->fPenSize.x, device->fPenSize.y);
- ::DeleteObject(hrgn);
- }
- else
- {
- if (renderVerb == FW_kFill)
- {
- plfmRect.right++;
- plfmRect.bottom++;
- }
-
- ::Ellipse(*device, plfmRect.left, plfmRect.top, plfmRect.right, plfmRect.bottom);
- }
- #endif
- #ifdef FW_BUILD_MAC
- FW_Boolean styleIsDash;
- FW_Boolean styleIsHairline;
- MacSelectInkAndStyle(device, FW_kGeometricShape, renderVerb, ink, style, styleIsDash, styleIsHairline);
-
- if (renderVerb == FW_kFrame)
- {
- FW_PrivSelectHairline hairSelector(styleIsHairline && !device->GetODCanvas()->IsDynamic(ev));
- ::FrameOval(&plfmRect);
- }
- else
- {
- switch (ink->GetTransferMode())
- {
- case FW_kErase:
- ::EraseOval(&plfmRect);
- break;
-
- case FW_kInvert:
- ::InvertOval(&plfmRect);
- break;
-
- default:
- ::PaintOval(&plfmRect);
- }
- }
- #endif
- }
- FW_SOM_CATCH
- }
-
- //----------------------------------------------------------------------------------------
- // FW_PrivRenderRoundRect
- //----------------------------------------------------------------------------------------
-
- void SL_API FW_PrivRenderRoundRect(Environment* ev,
- FW_SGraphicContext& gc,
- const FW_SRect& rect,
- const FW_SPoint& ovalSize,
- FW_ERenderVerbs renderVerb,
- FW_HInk ink,
- FW_HStyle style)
- {
- FW_RENDER_PROLOG
- FW_CHECK_RENDER_VERB
- FW_CHECK_INK
- FW_CHECK_STYLE
-
- FW_SOM_TRY
- {
- FW_CPlatformRect plfmRect;
- FW_PrivGC_LogicalToDeviceRect(ev, gc, rect, plfmRect);
- FW_FailOnEvError(ev);
-
- FW_CPlatformPoint plfmOvalSize;
- FW_PrivGC_LogicalToDeviceSize(ev, gc, ovalSize.x, ovalSize.y, plfmOvalSize);
- FW_FailOnEvError(ev);
-
- #ifdef FW_BUILD_WIN
- FW_Boolean frameBrush = device->SelectInkAndStyle(ink, style, FW_kGeometricShape, renderVerb);
-
- if (frameBrush)
- {
- HRGN hrgn = NULL;
- // There is a bug in Windows. If the size of the round rect is smaller than 1, we are dead.
- if ((plfmRect.right - plfmRect.left <= 1) || (plfmRect.bottom - plfmRect.top <= 1))
- hrgn = ::CreateEllipticRgn(plfmRect.left, plfmRect.top,
- plfmRect.right + 1, plfmRect.bottom + 1);
- else
- hrgn = ::CreateRoundRectRgn(plfmRect.left, plfmRect.top,
- plfmRect.right + 1, plfmRect.bottom + 1,
- plfmOvalSize.x, plfmOvalSize.y);
-
- ::FrameRgn(*device, hrgn, device->fGDIBrush.GetBrush(*device), device->fPenSize.x, device->fPenSize.y);
- ::DeleteObject(hrgn);
- }
- else
- {
- if (renderVerb == FW_kFill)
- {
- plfmRect.right++;
- plfmRect.bottom++;
- }
-
- ::RoundRect(*device,
- plfmRect.left, plfmRect.top,
- plfmRect.right, plfmRect.bottom,
- plfmOvalSize.x, plfmOvalSize.y);
- }
- #endif
- #ifdef FW_BUILD_MAC
- FW_Boolean styleIsDash;
- FW_Boolean styleIsHairline;
- MacSelectInkAndStyle(device, FW_kGeometricShape, renderVerb, ink, style, styleIsDash, styleIsHairline);
-
- if (renderVerb == FW_kFrame)
- {
- FW_PrivSelectHairline hairSelector(styleIsHairline && !device->GetODCanvas()->IsDynamic(ev));
- ::FrameRoundRect(&plfmRect, plfmOvalSize.h, plfmOvalSize.v);
- }
- else
- {
- switch (ink->GetTransferMode())
- {
- case FW_kErase:
- ::EraseRoundRect(&plfmRect, plfmOvalSize.h, plfmOvalSize.v);
- break;
- case FW_kInvert:
- ::InvertRoundRect(&plfmRect, plfmOvalSize.h, plfmOvalSize.v);
- break;
- default:
- ::PaintRoundRect(&plfmRect, plfmOvalSize.h, plfmOvalSize.v);
- }
- }
- #endif
- }
- FW_SOM_CATCH
- }
-
- //----------------------------------------------------------------------------------------
- // FW_PrivRenderRoundRect
- //----------------------------------------------------------------------------------------
-
- void SL_API FW_PrivRenderArc(Environment* ev,
- FW_SGraphicContext& gc,
- const FW_SRect& rect,
- short startAngle,
- short arcAngle,
- FW_ERenderVerbs renderVerb,
- FW_HInk ink,
- FW_HStyle style)
- {
- FW_RENDER_PROLOG
- FW_CHECK_RENDER_VERB
- FW_CHECK_INK
- FW_CHECK_STYLE
-
- FW_SOM_TRY
- {
- FW_CPlatformRect arcRect;
- FW_PrivGC_LogicalToDeviceRect(ev, gc, rect, arcRect);
- FW_FailOnEvError(ev);
-
- #ifdef FW_BUILD_WIN
- short angle1 = startAngle;
-
- // Normalize the start angle
- angle1 = angle1 % 360;
- if (angle1 < 0)
- angle1 += 360;
-
- // Compute and normalize the end angle
- short angle2 = angle1 + arcAngle;
- if (arcAngle < 0)
- {
- short temp = angle1;
- angle1 = angle2;
- angle2 = temp;
- }
-
- FW_CPlatformPoint endPoint, startPoint;
- FW_PrivCalcArcPoints(arcRect, angle1, endPoint); // on Windows, arc and pie are drawn counterclockwise
- FW_PrivCalcArcPoints(arcRect, angle2, startPoint);
-
- FW_Boolean frameBrush = device->SelectInkAndStyle(ink, style, FW_kGeometricShape, renderVerb);
-
- if (renderVerb == FW_kFrame)
- {
- if(frameBrush)
- {
- FW_CRect r = arcRect;
- ODRgnHandle rgnHandle = ::FW_CreateArcRegion(r, startAngle, arcAngle);
- ::FrameRgn(*device, rgnHandle, device->fGDIBrush.GetBrush(*device), device->fPenSize.x, device->fPenSize.y);
- ::FW_DisposeRegion(rgnHandle);
- }
- else
- {
- ::Arc(*device, arcRect.left, arcRect.top, arcRect.right, arcRect.bottom,
- startPoint.x, startPoint.y, endPoint.x, endPoint.y);
- }
- }
- else
- {
- arcRect.right++;
- arcRect.bottom++;
- ::Pie(*device, arcRect.left, arcRect.top, arcRect.right, arcRect.bottom,
- startPoint.x, startPoint.y, endPoint.x, endPoint.y);
- }
- #endif
- #ifdef FW_BUILD_MAC
- FW_Boolean styleIsDash;
- FW_Boolean styleIsHairline;
- MacSelectInkAndStyle(device, FW_kGeometricShape, renderVerb, ink, style, styleIsDash, styleIsHairline);
-
- if (renderVerb == FW_kFrame)
- {
- FW_PrivSelectHairline hairSelector(styleIsHairline && !device->GetODCanvas()->IsDynamic(ev));
- ::FrameArc(&arcRect, startAngle, arcAngle);
- }
- else
- {
- switch (ink->GetTransferMode())
- {
- case FW_kErase:
- ::EraseArc(&arcRect, startAngle, arcAngle);
- break;
- case FW_kInvert:
- ::InvertArc(&arcRect, startAngle, arcAngle);
- break;
- default:
- ::PaintArc(&arcRect, startAngle, arcAngle);
- }
- }
- #endif
- }
- FW_SOM_CATCH
- }
-
- //----------------------------------------------------------------------------------------
- // FW_RenderLine
- //----------------------------------------------------------------------------------------
-
- void SL_API FW_PrivRenderLine(Environment* ev,
- FW_SGraphicContext& gc,
- const FW_SPoint& start,
- const FW_SPoint& end,
- FW_ERenderVerbs renderVerb,
- FW_HInk ink,
- FW_HStyle style)
- {
- FW_RENDER_PROLOG
- FW_CHECK_RENDER_VERB
- FW_CHECK_INK
- FW_CHECK_STYLE
-
- FW_SOM_TRY
- {
- FW_CPlatformPoint plfmStart;
- FW_PrivGC_LogicalToDevicePoint(ev, gc, start, plfmStart);
- FW_FailOnEvError(ev);
-
-
- FW_CPlatformPoint plfmEnd;
- FW_PrivGC_LogicalToDevicePoint(ev, gc, end, plfmEnd);
- FW_FailOnEvError(ev);
-
- #ifdef FW_BUILD_WIN
- HDC hDC = device->GetPlatformCanvas();
- FW_Boolean frameBrush = device->SelectInkAndStyle(ink, style, FW_kGeometricShape, FW_kFrame);
-
- if (frameBrush)
- {
- int penSizeX = device->fPenSize.x;
- int penHalfX = penSizeX / 2;
- int penSizeY = device->fPenSize.y;
- int penHalfY = penSizeY / 2;
- if (plfmStart.x == plfmEnd.x)
- {
- device->fGDIBrush.SelectObject(hDC);
- ::PatBlt(hDC, plfmStart.x - penHalfX, plfmStart.y - penHalfY, penSizeX, plfmEnd.y - plfmStart.y, PATCOPY);
- }
- else if (plfmStart.y == plfmEnd.y)
- {
- device->fGDIBrush.SelectObject(hDC);
- ::PatBlt(hDC, plfmStart.x - penHalfX, plfmStart.y - penHalfY, plfmEnd.x - plfmStart.x, penSizeY, PATCOPY);
- }
- else
- {
- HRGN hRgn = ::FW_CreateLineRegion(FW_CPoint(plfmStart), FW_CPoint(plfmEnd), FW_CPoint(device->fPenSize));
- ::FillRgn(hDC, hRgn, device->fGDIBrush.GetBrush(hDC));
- ::DeleteObject(hRgn);
- }
- }
- else
- {
- ::MoveToEx(hDC, plfmStart.x, plfmStart.y, NULL);
- ::LineTo(hDC, plfmEnd.x, plfmEnd.y);
- }
- #endif
- #ifdef FW_BUILD_MAC
- FW_Boolean styleIsDash;
- FW_Boolean styleIsHairline;
- MacSelectInkAndStyle(device,
- FW_kLineShape,
- FW_kFrame, // We never use FW_kFill for lines
- ink,
- style,
- styleIsDash,
- styleIsHairline);
-
- short halfPenh = FW_QDGlobals.thePort->pnSize.h / 2;
- short halfPenv = FW_QDGlobals.thePort->pnSize.v / 2;
-
- ::MoveTo(plfmStart.h - halfPenh, plfmStart.v - halfPenv);
-
- {
- FW_PrivSelectHairline hairSelector(styleIsHairline && !device->GetODCanvas()->IsDynamic(ev));
-
- if (styleIsDash)
- {
- FW_CPrivMacDashDraw draw(style->GetDashStyle());
- draw.LineTo(plfmEnd.h - halfPenh, plfmEnd.v - halfPenv);
- }
- else
- {
- ::LineTo(plfmEnd.h - halfPenh, plfmEnd.v - halfPenv);
- }
- }
- #endif
- }
- FW_SOM_CATCH
- }
-
- //----------------------------------------------------------------------------------------
- // FW_PrivRenderRegion
- //----------------------------------------------------------------------------------------
-
- void SL_API FW_PrivRenderRegion(Environment* ev,
- FW_SGraphicContext& gc,
- ODShape* odShape,
- FW_ERenderVerbs renderVerb,
- FW_HInk ink,
- FW_HStyle style)
- {
- FW_RENDER_PROLOG
- FW_CHECK_RENDER_VERB
- FW_CHECK_INK
- FW_CHECK_STYLE
-
- FW_SOM_TRY
- {
- ODShape* deviceShape = FW_PrivGC_LogicalToDeviceShape(ev, gc, odShape);
- FW_FailOnEvError(ev);
-
- ODRgnHandle rgnHandle = ::FW_GetShapeRegion(ev, deviceShape);
- FW_ASSERT(rgnHandle != NULL);
-
- #ifdef FW_BUILD_WIN
- FW_ERenderVerbs localVerb = renderVerb == FW_kFrame ? FW_kFill : renderVerb;
- device->SelectInkAndStyle(ink, style, FW_kGeometricShapeWithInvert, localVerb);
-
- switch (renderVerb)
- {
- case FW_kFrame:
- ::FrameRgn(*device, rgnHandle, device->fGDIBrush.GetBrush(*device), device->fPenSize.x, device->fPenSize.y);
- break;
-
- case FW_kFill:
- if (ink->GetTransferMode() == FW_kInvert || ink->GetTransferMode() == FW_kHilite || ink->GetTransferMode() == FW_kSystemHilite)
- ::InvertRgn(*device, rgnHandle);
- else
- ::FillRgn(*device, rgnHandle, device->fGDIBrush.GetBrush(*device));
- break;
- }
- #endif
- #ifdef FW_BUILD_MAC
- FW_Boolean styleIsDash;
- FW_Boolean styleIsHairline;
- MacSelectInkAndStyle(device, FW_kGeometricShape, renderVerb, ink, style, styleIsDash, styleIsHairline);
-
- if (renderVerb == FW_kFrame)
- {
- FW_PrivSelectHairline hairSelector(styleIsHairline && !device->GetODCanvas()->IsDynamic(ev));
- ::FrameRgn(rgnHandle);
- }
- else
- {
- switch (ink->GetTransferMode())
- {
- case FW_kErase:
- ::EraseRgn(rgnHandle);
- break;
- case FW_kInvert:
- ::InvertRgn(rgnHandle);
- break;
- default:
- ::PaintRgn(rgnHandle);
- }
- }
- #endif
- deviceShape->Release(ev);
- }
- FW_SOM_CATCH
- }
-
- //----------------------------------------------------------------------------------------
- // FW_PrivRenderPolygon
- //----------------------------------------------------------------------------------------
-
- void SL_API FW_PrivRenderPolygon(Environment* ev,
- FW_SGraphicContext& gc,
- FW_HPolygon polygon,
- FW_ERenderVerbs renderVerb,
- FW_Boolean autoCloseFrame,
- FW_HInk ink,
- FW_HStyle style)
- {
- FW_RENDER_PROLOG
- FW_CHECK_RENDER_VERB
- FW_CHECK_INK
- FW_CHECK_STYLE
-
- FW_SOM_TRY
- {
- long count = polygon->GetCount();
- const FW_SPoint* points = polygon->GetPoints();
-
- #ifdef FW_BUILD_WIN
- // Convert points to platform points
- unsigned long plfmCount = count;
- FW_Boolean needClose = FALSE;
- if(renderVerb == FW_kFrame && autoCloseFrame && points[0] != points[count - 1])
- {
- ++ plfmCount;
- needClose = TRUE;
- }
-
- FW_CPlatformPoint* plfmPoints = new FW_CPlatformPoint[plfmCount];
- for(long i = 0; i < count; i ++)
- FW_PrivGC_LogicalToDevicePoint(gc, points[i], plfmPoints[i]);
-
- if(needClose)
- plfmPoints[plfmCount - 1] = plfmPoints[0];
-
- // Prepare the graphics device
- FW_Boolean frameBrush = device->SelectInkAndStyle(ink, style, FW_kGeometricShape, renderVerb);
-
- int penSizeX = device->fPenSize.x;
- int penHalfX = penSizeX / 2;
- int penSizeY = device->fPenSize.y;
- int penHalfY = penSizeY / 2;
-
- HDC hDC = *device;
-
- // Render the polygon
- switch (renderVerb)
- {
- case FW_kFrame:
- if(frameBrush)
- {
- // Doing it like this is way, way faster than creating a polygon
- // region for the whole thing and framing it
- FW_CPlatformPoint pt0, pt1;
- BOOL bBrushSelected = FALSE;
-
- for(unsigned long p = 0; p < plfmCount - 1; p ++)
- {
- pt0 = plfmPoints[p];
- pt1 = plfmPoints[p + 1];
-
- if (pt0.x == pt1.x)
- {
- if (!bBrushSelected)
- {
- device->fGDIBrush.SelectObject(hDC);
- bBrushSelected = TRUE;
- }
-
- ::PatBlt(hDC, pt0.x - penHalfX, pt0.y - penHalfY, penSizeX, pt1.y - pt0.y, PATCOPY);
- }
- else if (pt0.y == pt1.y)
- {
- if (!bBrushSelected)
- {
- device->fGDIBrush.SelectObject(hDC);
- bBrushSelected = TRUE;
- }
-
- ::PatBlt(hDC, pt0.x - penHalfX, pt0.y - penHalfY, pt1.x - pt0.x, penSizeY, PATCOPY);
- }
- else
- {
- HRGN hRgn = ::FW_CreateLineRegion(FW_CPoint(pt0), FW_CPoint(pt1), FW_CPoint(device->fPenSize));
- ::FillRgn(hDC, hRgn, device->fGDIBrush.GetBrush(hDC));
- ::DeleteObject(hRgn);
- }
- }
- }
- else
- {
- ::Polyline(hDC, plfmPoints, plfmCount);
- }
- break;
-
- case FW_kFill:
- ::Polygon(hDC, plfmPoints, plfmCount);
- break;
- }
-
- delete[] plfmPoints;
- #endif
- #ifdef FW_BUILD_MAC
- // Create a polygon
- GrafPtr savePort;
- ::GetPort(&savePort);
- ::SetPort(FW_gScratchPort);
- PolyHandle polyHandle = ::OpenPoly();
-
- if(polyHandle == NULL)
- {
- ::SetPort(savePort);
- FW_Failure(FW_xMemoryExhausted);
- }
-
- FW_CPlatformPoint plfmPoint;
- FW_PrivGC_LogicalToDevicePoint(ev, gc, points[0], plfmPoint);
- FW_FailOnEvError(ev);
-
- ::MoveTo(plfmPoint.h, plfmPoint.v);
-
- for(long i = 1; i < count; i ++)
- {
- FW_PrivGC_LogicalToDevicePoint(ev, gc, points[i], plfmPoint);
- FW_FailOnEvError(ev);
-
- ::LineTo(plfmPoint.h, plfmPoint.v);
- }
-
- // Close the polygon if needed
- if(renderVerb == FW_kFrame && autoCloseFrame && points[0] != points[count - 1])
- {
- FW_PrivGC_LogicalToDevicePoint(ev, gc, points[0], plfmPoint);
- FW_FailOnEvError(ev);
-
- ::LineTo(plfmPoint.h, plfmPoint.v);
- }
-
- ::ClosePoly();
- ::SetPort(savePort);
-
- // Prepare the grafport
- FW_Boolean styleIsDash;
- FW_Boolean styleIsHairline;
- MacSelectInkAndStyle(device, FW_kGeometricShape, renderVerb, ink, style, styleIsDash, styleIsHairline);
-
- // Render the polygon
- if (renderVerb == FW_kFrame)
- {
- FW_PrivSelectHairline hairSelector(styleIsHairline && !device->GetODCanvas()->IsDynamic(ev));
-
- if (styleIsDash)
- {
- FW_CPrivMacDashDraw draw(style->GetDashStyle());
- short nPolyCount = ((*polyHandle)->polySize - 10) / sizeof(Point);
- ::MoveTo((*polyHandle)->polyPoints[0].h, (*polyHandle)->polyPoints[0].v);
- for (short n = 1; n < nPolyCount; ++ n)
- draw.LineTo((*polyHandle)->polyPoints[n].h, (*polyHandle)->polyPoints[n].v);
- }
- else
- {
- ::FramePoly(polyHandle);
- }
- }
- else
- {
- switch (ink->GetTransferMode())
- {
- case FW_kErase:
- ::ErasePoly(polyHandle);
- break;
- case FW_kInvert:
- ::InvertPoly(polyHandle);
- break;
- default:
- ::PaintPoly(polyHandle);
- }
- }
-
- ::KillPoly(polyHandle);
- #endif
- }
- FW_SOM_CATCH
- }
-
- //----------------------------------------------------------------------------------------
- // FW_PrivRenderTextString
- //----------------------------------------------------------------------------------------
-
- void SL_API FW_PrivRenderTextString(Environment* ev,
- FW_SGraphicContext& gc,
- FW_HString string,
- const FW_SPoint& position,
- FW_TextAlignment textAlignment,
- FW_ERenderVerbs renderVerb,
- FW_HInk ink,
- FW_HFont font)
- {
- FW_SOM_TRY
- {
- FW_CPrivTextBuffer buffer(string);
- PrivRenderTextBuffer(ev, gc, &buffer, position, textAlignment, renderVerb, ink, font);
- }
- FW_SOM_CATCH
- }
-
- //----------------------------------------------------------------------------------------
- // FW_PrivRenderTextReader
- //----------------------------------------------------------------------------------------
-
- void SL_API FW_PrivRenderTextReader(Environment* ev,
- FW_SGraphicContext& gc,
- FW_HTextReader reader,
- const FW_SPoint& position,
- FW_TextAlignment textAlignment,
- FW_ERenderVerbs renderVerb,
- FW_HInk ink,
- FW_HFont font)
- {
- FW_SOM_TRY
- {
- FW_CPrivTextBuffer buffer(reader);
- PrivRenderTextBuffer(ev, gc, &buffer, position, textAlignment, renderVerb, ink, font);
- }
- FW_SOM_CATCH
- }
-
- //----------------------------------------------------------------------------------------
- // PrivRenderTextBuffer
- //----------------------------------------------------------------------------------------
-
- static void PrivRenderTextBuffer(Environment* ev,
- FW_SGraphicContext& gc,
- FW_CPrivTextBuffer* textBuffer,
- const FW_SPoint& position,
- FW_TextAlignment textAlignment,
- FW_ERenderVerbs renderVerb,
- FW_HInk ink,
- FW_HFont font)
- {
- FW_RENDER_PROLOG
- FW_CHECK_RENDER_VERB
- FW_CHECK_FONT
- FW_CHECK_INK
-
- FW_ASSERT(textBuffer != NULL);
- if (textBuffer->IsDone()) // No text to draw
- return;
-
- FW_CPlatformPoint plfmPos;
- FW_PrivGC_LogicalToDevicePoint(ev, gc, position, plfmPos);
- FW_FailOnEvError(ev);
-
- // ----- RenderText only cares about the first line -----
- const char* text;
- FW_ByteCount count;
- textBuffer->GetCurrentLine(text, count);
-
- #ifdef FW_BUILD_WIN
- device->SelectInkAndFont(ink, font);
-
- // ----- Set the text alignment - always use TA_UPDATECP (see below)
- TEXTMETRIC tm;
- UINT newAlign = TA_UPDATECP;
-
- switch (textAlignment & FW_kPrivTextAlignVertAlignMask)
- {
- case FW_kTextAlignTop:
- newAlign |= TA_TOP;
- break;
-
- case FW_kTextAlignBottom:
- newAlign |= TA_BOTTOM;
- break;
-
- case FW_kTextAlignVCenter:
- ::GetTextMetrics(*device, &tm);
- plfmPos.y -= (tm.tmHeight - tm.tmInternalLeading) / 2;
- break;
-
- case FW_kTextAlignBaseLine:
- newAlign |= TA_BASELINE;
- break;
- }
-
- switch (textAlignment & FW_kPrivTextAlignHorzAlignMask)
- {
- case FW_kTextAlignLeft:
- newAlign |= TA_LEFT;
- break;
-
- case FW_kTextAlignRight:
- newAlign |= TA_RIGHT;
- break;
-
- case FW_kTextAlignHCenter:
- newAlign |= TA_CENTER;
- break;
- }
-
- // It is necessary to use TA_UPDATECP because the next call may want to use
- // FW_kTextAlignUseCurrentPos. However, TA_UPDATECP also means "use CP", so
- // if this is not what the user wants, we should move to the right pos first
-
- if((textAlignment & FW_kPrivTextAlignUsePosMask) == FW_kTextAlignUseSpecifiedPos)
- ::MoveToEx(*device, plfmPos.x, plfmPos.y, NULL);
-
- ::SetTextAlign(*device, newAlign);
- ::TextOut(*device,
- 0, 0, // we use TA_UPDATECP, remember?
- text,
- count);
-
- ::SetTextAlign(*device, TA_LEFT | TA_TOP | TA_NOUPDATECP); // restore the flags
- #endif
- #ifdef FW_BUILD_MAC
- device->SelectInk(ink, FW_kTypographicShape, FW_kFill);
- device->SelectFont(font, TRUE); // SetInGrafPort called by SelectFont
-
- // ----- The Mac only knows to draw text from the baseline, so we need to do some adjustment
- FW_CPlatformPoint plfmTextPos = MacCalcTextPosition(device, count, text, textAlignment, plfmPos);
-
- // ----- Draw the text
- ::MoveTo(plfmTextPos.h, plfmTextPos.v);
- ::DrawText(text, 0, count);
-
- // ----- StrikeOut if necessary
- if ((font->GetFontStyle() & FW_kStrikeOut) != 0)
- MacStrikeOut(device, plfmTextPos.h, plfmTextPos.v);
- #endif
- }
-
- //----------------------------------------------------------------------------------------
- // FW_PrivRenderTextBoxString
- //----------------------------------------------------------------------------------------
-
- FW_Fixed SL_API FW_PrivRenderTextBoxString(Environment* ev,
- FW_SGraphicContext& gc,
- FW_HString string,
- const FW_SRect& box,
- FW_TextBoxOptions options,
- FW_ERenderVerbs renderVerb,
- FW_HInk ink,
- FW_HFont font)
- {
- FW_SOM_TRY
- {
- FW_CPrivTextBuffer buffer(string);
- return PrivRenderTextBoxBuffer(ev, gc, &buffer, box, options, renderVerb, ink, font);
- }
- FW_SOM_CATCH
- return FW_kFixed0;
- }
-
- //----------------------------------------------------------------------------------------
- // FW_PrivRenderTextBoxReader
- //----------------------------------------------------------------------------------------
-
- FW_Fixed SL_API FW_PrivRenderTextBoxReader(Environment* ev,
- FW_SGraphicContext& gc,
- FW_HTextReader reader,
- const FW_SRect& box,
- FW_TextBoxOptions options,
- FW_ERenderVerbs renderVerb,
- FW_HInk ink,
- FW_HFont font)
- {
- FW_SOM_TRY
- {
- FW_CPrivTextBuffer buffer(reader);
- return PrivRenderTextBoxBuffer(ev, gc, &buffer, box, options, renderVerb, ink, font);
- }
- FW_SOM_CATCH
- return FW_kFixed0;
- }
-
- //----------------------------------------------------------------------------------------
- // PrivRenderTextBoxBuffer
- //----------------------------------------------------------------------------------------
-
- static FW_Fixed PrivRenderTextBoxBuffer(Environment* ev,
- FW_SGraphicContext& gc,
- FW_CPrivTextBuffer* textBuffer,
- const FW_SRect& box,
- FW_TextBoxOptions options,
- FW_ERenderVerbs renderVerb,
- FW_HInk ink,
- FW_HFont font)
- {
- FW_RENDER_PROLOG
- FW_CHECK_FONT
- FW_CHECK_INK
-
- FW_ASSERT(textBuffer != NULL);
- if (renderVerb == FW_kNoRendering || textBuffer->IsDone())
- return box.top;
-
- FW_CPlatformRect plfmBox;
- FW_PrivGC_LogicalToDeviceRect(ev, gc, box, plfmBox);
- FW_FailOnEvError(ev);
-
- #ifdef FW_BUILD_WIN
- device->SelectInkAndFont(ink, font);
- #endif
- #ifdef FW_BUILD_MAC
- device->SelectInk(ink, FW_kTypographicShape, FW_kFill);
- device->SelectFont(font, TRUE);
- #endif
-
- FW_PlatformCoordinate bottom = PrivTextBox(ev, device, textBuffer, plfmBox, options, TRUE, font);
-
- if (bottom != plfmBox.bottom)
- {
- FW_CPlatformPoint pt(0, bottom);
- FW_CPoint cPt;
- FW_PrivGC_DeviceToLogicalPoint(ev, gc, pt, cPt);
- FW_FailOnEvError(ev);
- return cPt.y;
- }
-
- return box.bottom;
- }
-
- //----------------------------------------------------------------------------------------
- // FW_PrivTextBoxSizeString
- //----------------------------------------------------------------------------------------
-
- void SL_API FW_PrivTextBoxSizeString(Environment* ev,
- FW_SGraphicContext& gc,
- FW_HString string,
- FW_HFont font,
- FW_TextBoxOptions options,
- FW_SRect& textBox)
- {
- FW_SOM_TRY
- {
- FW_CPrivTextBuffer buffer(string);
- PrivTextBoxSizeBuffer(ev, gc, &buffer, font, options, textBox);
- }
- FW_SOM_CATCH
- }
-
- //----------------------------------------------------------------------------------------
- // FW_PrivTextBoxSizeReader
- //----------------------------------------------------------------------------------------
-
- void SL_API FW_PrivTextBoxSizeReader(Environment* ev,
- FW_SGraphicContext& gc,
- FW_HTextReader reader,
- FW_HFont font,
- FW_TextBoxOptions options,
- FW_SRect& textBox)
- {
- FW_SOM_TRY
- {
- FW_CPrivTextBuffer buffer(reader);
- PrivTextBoxSizeBuffer(ev, gc, &buffer, font, options, textBox);
- }
- FW_SOM_CATCH
- }
-
- //----------------------------------------------------------------------------------------
- // PrivTextBoxSizeBuffer
- //----------------------------------------------------------------------------------------
-
- static void PrivTextBoxSizeBuffer(Environment* ev,
- FW_SGraphicContext& gc,
- FW_CPrivTextBuffer *textBuffer,
- FW_HFont font,
- FW_TextBoxOptions options,
- FW_SRect& textBox)
- {
- FW_RENDER_PROLOG
- FW_CHECK_FONT
-
- FW_ASSERT((const void*)font != NULL);
- FW_ASSERT(textBuffer != NULL);
-
- FW_CPlatformRect plfmBox;
- FW_PrivGC_LogicalToDeviceRect(ev, gc, textBox, plfmBox);
- FW_FailOnEvError(ev);
-
- if (textBuffer->IsDone())
- {
- plfmBox.bottom = plfmBox.top;
- }
- else
- {
- device->SelectFont(font, TRUE); // TRUE: scale
- plfmBox.bottom = PrivTextBox(ev, device, textBuffer, plfmBox, options, FALSE, font); // FALSE: don't draw
- }
-
- FW_CPoint textBoxSize;
- FW_PrivGC_DeviceToLogicalSize(ev, gc, plfmBox.right, plfmBox.bottom, textBoxSize);
- FW_FailOnEvError(ev);
-
- textBox.right = textBox.left + textBoxSize.x;
- textBox.bottom = textBox.top + textBoxSize.y;
- }
-
- //----------------------------------------------------------------------------------------
- // FW_PrivCalcTextExtentString
- //----------------------------------------------------------------------------------------
-
- void SL_API FW_PrivCalcTextExtentString(Environment* ev,
- FW_SGraphicContext& gc,
- FW_HString string,
- FW_HFont font,
- FW_SPoint& textExtent)
- {
- FW_SOM_TRY
- {
- FW_CPrivTextBuffer buffer(string);
- PrivTextExtentBuffer(ev, gc, &buffer, font, textExtent);
- }
- FW_SOM_CATCH
- }
-
- //----------------------------------------------------------------------------------------
- // FW_PrivCalcTextExtentReader
- //----------------------------------------------------------------------------------------
-
- void SL_API FW_PrivCalcTextExtentReader(Environment* ev,
- FW_SGraphicContext& gc,
- FW_HTextReader reader,
- FW_HFont font,
- FW_SPoint& textExtent)
- {
- FW_SOM_TRY
- {
- FW_CPrivTextBuffer buffer(reader);
- PrivTextExtentBuffer(ev, gc, &buffer, font, textExtent);
- }
- FW_SOM_CATCH
- }
-
- //----------------------------------------------------------------------------------------
- // PrivTextExtentBuffer
- //----------------------------------------------------------------------------------------
-
- static void PrivTextExtentBuffer(Environment* ev,
- FW_SGraphicContext& gc,
- FW_CPrivTextBuffer* textBuffer,
- FW_HFont font,
- FW_SPoint& textExtent)
- {
- FW_RENDER_PROLOG
- FW_CHECK_FONT
-
- if (textBuffer->IsDone())
- {
- textExtent = FW_kZeroPoint;
- return;
- }
-
- device->SelectFont(font, TRUE);
-
- // ----- TextExtent only cares about the first line -----
- FW_ByteCount count;
- const char* text;
- textBuffer->GetCurrentLine(text, count);
-
- #ifdef FW_BUILD_WIN
- SIZE size;
- ::GetTextExtentPoint32(*device, text, count, &size);
- FW_CPlatformPoint plfmExtent(size.cx, size.cy);
- #endif
- #ifdef FW_BUILD_MAC
- FontInfo fi;
- ::GetFontInfo(&fi);
-
- FW_CPlatformPoint plfmExtent(
- ::TextWidth(text, 0, count),
- fi.ascent + fi.descent);
- #endif
-
- FW_PrivGC_DeviceToLogicalSize(ev, gc, plfmExtent.X(), plfmExtent.Y(), textExtent);
- FW_FailOnEvError(ev);
- }
-
- //----------------------------------------------------------------------------------------
- // FW_PrivRenderPicture
- //----------------------------------------------------------------------------------------
-
- void SL_API FW_PrivRenderPicture(Environment* ev,
- FW_SGraphicContext& gc,
- FW_HPicture picture,
- const FW_SRect& dstRect,
- FW_ERenderVerbs renderVerb)
- {
- FW_RENDER_PROLOG
- FW_CHECK_RENDER_VERB
-
- FW_SOM_TRY
- {
- FW_ASSERT(picture != NULL);
- FW_PlatformPict pict = picture->GetPlatformPict();
- FW_CPlatformRect plfmRect;
- FW_PrivGC_LogicalToDeviceRect(ev, gc, dstRect, plfmRect);
- FW_FailOnEvError(ev);
-
- #ifdef FW_BUILD_WIN
- ::PlayEnhMetaFile(*device, pict, &plfmRect);
- #endif
- #ifdef FW_BUILD_MAC
- ::DrawPicture(pict, &plfmRect);
- #endif
- }
- FW_SOM_CATCH
- }
-
- //----------------------------------------------------------------------------------------
- // FW_PrivRenderBitmap
- //----------------------------------------------------------------------------------------
-
- void SL_API FW_PrivRenderBitmap(Environment* ev,
- FW_SGraphicContext& gc,
- FW_HBitmap bitmap,
- const FW_SRect& srcRect,
- const FW_SRect& dstRect,
- FW_ERenderVerbs renderVerb,
- FW_HInk ink)
- {
- FW_CHECK_RENDER_VERB
-
- // If erase, invert or hilite is used then simply erase/invert/hilite the dst Rectangle
- FW_TransferModes transferMode = ink->GetTransferMode();
- if (transferMode == FW_kErase || transferMode == FW_kInvert || transferMode == FW_kHilite || transferMode == FW_kSystemHilite)
- {
- FW_CStyle style(FW_kNormalStyle);
- FW_PrivRenderRect(ev, gc, dstRect, FW_kFill, ink, style);
- return;
- }
-
- FW_RENDER_PROLOG
-
- FW_ASSERT(bitmap != NULL);
-
- FW_SOM_TRY
- {
- // Convert source and destination rectangles
- FW_CPlatformRect plfmDstRect;
- FW_PrivGC_LogicalToDeviceRect(ev, gc, dstRect, plfmDstRect);
- FW_FailOnEvError(ev);
-
- FW_CPlatformRect plfmSrcRect = srcRect;
-
- #ifdef FW_BUILD_WIN
- HDC hDC = *device;
-
- ::SetTextColor(hDC, ink->GetForeColor());
- ::SetBkColor(hDC, ink->GetBackColor());
-
- HBITMAP plfmBitmap = bitmap->GetPlatformBitmap();
-
- HDC memoryDC = ::CreateCompatibleDC(hDC);
- HBITMAP oldBitmap = (HBITMAP) ::SelectObject(memoryDC, plfmBitmap);
-
- HPALETTE hPal = bitmap->GetPalette();
- HPALETTE hPalOld = NULL;
- if (hPal != NULL)
- {
- hPalOld = ::SelectPalette(hDC, hPal, FALSE);
- ::RealizePalette(hDC);
- }
-
- ::StretchBlt(hDC,
- plfmDstRect.left,
- plfmDstRect.top,
- plfmDstRect.right - plfmDstRect.left,
- plfmDstRect.bottom - plfmDstRect.top,
- memoryDC,
- plfmSrcRect.left,
- plfmSrcRect.top,
- plfmSrcRect.right - plfmSrcRect.left,
- plfmSrcRect.bottom - plfmSrcRect.top,
- FW_PrivWinConvertRasterOp(ink->GetTransferMode()));
-
- if (hPalOld)
- ::SelectPalette(hDC, hPalOld, TRUE);
-
- ::SelectObject(memoryDC, oldBitmap);
- ::DeleteDC(memoryDC);
- #endif
- #ifdef FW_BUILD_MAC
- device->SelectInk(ink, FW_kImageShape, FW_kFill); // Never use FW_kFrame for bitmap
- device->SetInGrafPort();
-
- PixMapHandle pmh = bitmap->MacLockPixels();
- ::CopyBits((BitMap*)*pmh, &FW_QDGlobals.thePort->portBits,
- &plfmSrcRect, &plfmDstRect,
- FW_PrivMacGetMacTransferMode(ink->GetTransferMode()), NULL);
- bitmap->MacUnlockPixels();
- #endif
- }
- FW_SOM_CATCH
- }
-
- //----------------------------------------------------------------------------------------
- // FW_PrivRenderIcon
- //----------------------------------------------------------------------------------------
-
- void SL_API FW_PrivRenderIcon(Environment* ev,
- FW_SGraphicContext& gc,
- FW_HIcon icon,
- const FW_SRect& rect,
- FW_RenderIconTransform transform,
- FW_RenderIconAlignment alignment,
- FW_ERenderVerbs renderVerb)
- {
- FW_RENDER_PROLOG
- FW_CHECK_RENDER_VERB
-
- FW_ASSERT(icon != NULL);
-
- FW_SOM_TRY
- {
- FW_PlatformIcon hIcon = icon->GetPlatformIcon();
-
- FW_PlatformRect plfmDstRect;
- FW_PrivGC_LogicalToDeviceRect(ev, gc, rect, plfmDstRect);
- FW_FailOnEvError(ev);
-
- #ifdef FW_BUILD_WIN
- FW_CPoint iconSize;
- icon->GetIconSize(iconSize);
-
- short xSize = iconSize.IntX(), ySize = iconSize.IntY();
-
- // Horizontal alignment
- if (alignment & FW_kIconAlignCenter)
- {
- plfmDstRect.left = (plfmDstRect.right + plfmDstRect.left - xSize) / 2;
- plfmDstRect.right = plfmDstRect.left + xSize;
- }
- else if (alignment & FW_kIconAlignLeft)
- {
- plfmDstRect.right = plfmDstRect.left + xSize;
- }
- else if (alignment & FW_kIconAlignRight)
- {
- plfmDstRect.left = plfmDstRect.right - xSize;
- }
-
- // Vertical alignment
- if (alignment & FW_kIconAlignVCenter)
- {
- plfmDstRect.top = (plfmDstRect.bottom + plfmDstRect.top - ySize) / 2;
- plfmDstRect.bottom = plfmDstRect.top + ySize;
- }
- else if (alignment & FW_kIconAlignTop)
- {
- plfmDstRect.bottom = plfmDstRect.top + ySize;
- }
- else if (alignment & FW_kIconAlignBottom)
- {
- plfmDstRect.top = plfmDstRect.bottom - ySize;
- }
-
- // [HLX] Need to support tranform
- ::DrawIconEx(*device, plfmDstRect.left, plfmDstRect.top, hIcon,
- plfmDstRect.right - plfmDstRect.left,
- plfmDstRect.bottom - plfmDstRect.top,
- 0, NULL, DI_NORMAL);
- #endif
-
- #ifdef FW_BUILD_MAC
- FW_PrivMacSetStdColors();
- ::PlotIconSuite(&plfmDstRect, alignment, transform, hIcon);
- #endif
- }
- FW_SOM_CATCH
- }
-
- //========================================================================================
- // Local helpers
- //========================================================================================
-
- //----------------------------------------------------------------------------------------
- // PrivTextBox
- //----------------------------------------------------------------------------------------
-
- static FW_PlatformCoordinate PrivTextBox(Environment* ev,
- FW_CPrivGraphicsDevice* device,
- FW_CPrivTextBuffer *textBuffer,
- const FW_CPlatformRect& box,
- FW_TextBoxOptions options,
- FW_Boolean draw,
- FW_HFont font)
- {
- FW_UNUSED(ev);
-
- if (textBuffer->IsDone())
- return box.top;
-
- // ----- Check options for consistency
- FW_TextBoxOptions opt = options;
-
- if (!draw)
- opt &= ~FW_kTextBoxClipToBox;
-
- if ((opt & FW_kTextBoxSingleLine) != 0)
- {
- opt &= ~FW_kTextBoxWordWrap;
- opt &= ~FW_kTextBoxWordBreak;
- }
-
- if ((opt & FW_kTextBoxWordWrap) != 0)
- {
- opt &= ~FW_kTextBoxJustifyBottom;
- opt &= ~FW_kTextBoxJustifyVCenter;
- }
-
- FW_CharacterPosition segStart; // start of the current string segment
- FW_CharacterCount segLen; // its length (charcter count)
- FW_PlatformCoordinate actualWidth; // its actual width (pixels)
- FW_PlatformCoordinate maxWidth = box.right - box.left;
-
- FW_Boolean bClip = (opt & FW_kTextBoxClipToBox) != 0;
-
- #ifdef FW_BUILD_WIN
- // ----- Set the clipping region if we need to
- HDC hDC = device->GetPlatformCanvas();
- int savedDC = 0;
- if (bClip)
- {
- savedDC = ::SaveDC(hDC);
- ::IntersectClipRect(hDC,
- box.left, box.top,
- box.right, box.bottom);
- }
-
- // ----- Get the font height
- TEXTMETRIC textMetric;
- ::GetTextMetrics(hDC, &textMetric);
- FW_PlatformCoordinate fontHeight = textMetric.tmHeight + textMetric.tmExternalLeading;
-
- FW_PlatformCoordinate drawPosY = box.top;
- FW_PlatformCoordinate drawPosX = box.left;
- #endif
- #ifdef FW_BUILD_MAC
- // ----- Set the clipping region if we need to
- RgnHandle oldClipRgn = 0;
- if (bClip)
- {
- oldClipRgn = device->GetClip();
- device->IntersectClipRect(ev, box);
- }
-
- // ----- Get the font height -----
- FontInfo fi;
- ::GetFontInfo(&fi);
- FW_PlatformCoordinate fontHeight = fi.ascent + fi.descent + fi.leading;
-
- FW_PlatformCoordinate drawPosY = box.top + fi.ascent;
- FW_PlatformCoordinate drawPosX = box.left;
-
- FW_Boolean bIsStrikeOut = (font->GetFontStyle() & FW_kStrikeOut) != 0;
- #endif
-
- // ----- Check vertical jusitficaiton
- switch (opt & FW_kPrivTextBoxVertJusificationMask)
- {
- case FW_kTextBoxJustifyVCenter:
- #ifdef FW_BUILD_WIN
- drawPosY = (box.top + box.bottom - fontHeight) / 2;
- #endif
- #ifdef FW_BUILD_MAC
- drawPosY = (box.top + box.bottom + fi.ascent - fi.descent) / 2;
- #endif
- break;
-
- case FW_kTextBoxJustifyBottom:
- drawPosY = box.bottom - fontHeight;
- break;
- }
-
- // ----- Draw string segments one by one
- FW_Boolean wordWrap = (opt & FW_kTextBoxWordWrap) != 0;
- FW_Boolean wordBreak = (opt & FW_kTextBoxWordBreak) != 0;
- FW_Boolean reachedBottom = FALSE;
- while (TRUE)
- {
- const char* line;
- FW_ByteCount lineLength;
- textBuffer->GetCurrentLine(line, lineLength);
-
- // ----- Draw the current segment
- FW_Boolean bCalledBefore = FALSE;
- while (!reachedBottom && FW_PrivGetStringSegment(*device, bCalledBefore,
- line, lineLength, segStart, segLen, maxWidth, actualWidth, wordWrap, wordBreak))
- {
- // ----- Check horizontal jusitficaiton
- switch (opt & FW_kPrivTextBoxHorzJusificationMask)
- {
- case FW_kTextAlignHCenter:
- drawPosX = (box.left + box.right - actualWidth) / 2;
- break;
-
- case FW_kTextAlignRight:
- drawPosX = box.right - actualWidth;
- break;
- }
-
- if (draw)
- {
- // ----- Draw the next line -----
- #ifdef FW_BUILD_WIN
- ::TextOut(hDC, drawPosX, drawPosY, line + segStart, segLen);
- #endif
- #ifdef FW_BUILD_MAC
- ::MoveTo(drawPosX, drawPosY);
- ::DrawText((Ptr)line, segStart, segLen);
-
- // ----- StrikeOut if necessary -----
- if (bIsStrikeOut)
- MacStrikeOut(device, drawPosX, drawPosY);
- #endif
- }
-
- drawPosY += fontHeight; // Move one line down
- line += segLen + segStart; // move on to the next segment
- lineLength -= segLen + segStart;
-
- // see if we've gotten to the bottom of the rectangle and need not to continue
- reachedBottom = bClip && (drawPosY > box.bottom);
- }
-
- if (textBuffer->IsDone())
- break;
-
- if (reachedBottom)
- break;
-
- textBuffer->Advance();
- }
-
- // ----- Restore clipping region
- #ifdef FW_BUILD_WIN
- if (savedDC != 0)
- ::RestoreDC(*device, savedDC);
- #endif
- #ifdef FW_BUILD_MAC
- if (oldClipRgn != NULL)
- {
- ::SetClip(oldClipRgn);
- ::FW_DisposeRegion(oldClipRgn);
- }
-
- #endif
-
- // ----- Return the result ----
- #ifdef FW_BUILD_WIN
- return drawPosY;
- #endif
- #ifdef FW_BUILD_MAC
- return drawPosY - fi.ascent;
- #endif
- }
-
- #ifdef FW_BUILD_MAC
-
- //========================================================================================
- // Macintosh-specific implementation
- //========================================================================================
-
- FW_DEFINE_AUTO(FW_PrivSelectHairline)
-
- FW_PrivSelectHairline::FW_PrivSelectHairline(FW_Boolean setHairline)
- : fData(NULL)
- {
- if(setHairline)
- {
- // this memory allocation is unlikely to fail,
- // and if it does it would result in a line being drawn too fat,
- // so on failure we just refrain from setting the width
- fData = FW_PrivMemoryManager_AllocateSystemHandle(sizeof(Point));
- if(fData != nil)
- {
- const short kScaleNumerator = 1;
- const short kScaleDenominator = 28; // can be from 1 thru 128
-
- Point tempData = { kScaleNumerator, kScaleDenominator };
- **(Point**)fData = tempData;
-
- ::PicComment(eSetLineWidthPicComment, sizeof(Point), fData);
- }
- }
-
- FW_END_CONSTRUCTOR
- }
-
- FW_PrivSelectHairline::~FW_PrivSelectHairline()
- {
- FW_START_DESTRUCTOR
-
- if(fData != NULL)
- {
- // this is done in two passes for stylewriter and laserwriter.
-
- {
- // nothing here will move memory while we have this dereferenced
- // it still contains the ratio that was set in the ctor
- Point *pData = *(Point**)fData;
- Point tempData = *pData;
-
- // 1. invert the numerator and denominator to un-scale the pen
- pData->h = tempData.v;
- pData->v = tempData.h;
- }
-
- // this inverts the scale -- for the stylewriter
- ::PicComment(eSetLineWidthPicComment, 4, fData);
-
- **(long**)fData = 0x00010001; // set the handle data to {1,1}
-
- // this is explicitly 1, 1 for the laserwriter
- ::PicComment(eSetLineWidthPicComment, 4, fData);
-
- FW_PrivMemoryManager_FreeSystemHandle(fData);
- }
- }
-
- //----------------------------------------------------------------------------------------
- // MacSelectInkAndStyle
- //----------------------------------------------------------------------------------------
-
- static void MacSelectInkAndStyle(
- FW_CPrivGraphicsDevice* device,
- FW_EPrivShapeCategories shapeCategory,
- FW_ERenderVerbs renderVerb,
- FW_HInk ink,
- FW_HStyle style,
- FW_Boolean& styleIsDash,
- FW_Boolean& styleIsHairline)
- {
- device->SelectInk(ink, shapeCategory, renderVerb);
- device->SelectStyle(style, ink->GetTransferMode(), styleIsDash, styleIsHairline);
- device->SetInGrafPort();
- }
-
- //----------------------------------------------------------------------------------------
- // MacCalcTextPosition
- //----------------------------------------------------------------------------------------
-
- static FW_CPlatformPoint MacCalcTextPosition(
- FW_CPrivGraphicsDevice* device,
- short byteCount, const char* text,
- FW_TextAlignment textAlignment,
- const FW_CPlatformPoint& position)
- {
- #ifndef FW_DEBUG
- FW_UNUSED(device);
- #endif
-
- FW_ASSERT(device->GetPlatformCanvas() == FW_QDGlobals.thePort);
-
- FW_ASSERT(text != NULL);
-
- FW_CPlatformPoint plfmPos(position);
-
- if((textAlignment & FW_kPrivTextAlignUsePosMask) == FW_kTextAlignUseCurrentPos)
- {
- ::GetPen(&plfmPos);
- }
- else
- {
- // ----- Adjust Horizontal position
- FW_TextAlignment hAlign = textAlignment & FW_kPrivTextAlignHorzAlignMask;
- if (hAlign != FW_kTextAlignLeft)
- {
- short textWidth = ::TextWidth(text, 0, byteCount);
- if (hAlign == FW_kTextAlignRight)
- plfmPos.h -= textWidth;
- else
- plfmPos.h -= (textWidth / 2);
- }
- }
-
- // ----- In both cases we need to adjust the vertical position
- FW_TextAlignment vAlign = textAlignment & FW_kPrivTextAlignVertAlignMask;
- if (vAlign != FW_kTextAlignBaseLine)
- {
- FontInfo fi;
- ::GetFontInfo(&fi);
- switch (vAlign)
- {
- case FW_kTextAlignTop:
- plfmPos.v += fi.ascent;
- break;
-
- case FW_kTextAlignBottom:
- plfmPos.v -= fi.descent;
- break;
-
- case FW_kTextAlignVCenter:
- plfmPos.v += fi.ascent - ((fi.descent + fi.ascent) / 2);
- break;
- }
- }
-
- return plfmPos;
- }
-
- //----------------------------------------------------------------------------------------
- // MacStrikeOut
- //----------------------------------------------------------------------------------------
-
- static void MacStrikeOut(
- FW_CPrivGraphicsDevice* device,
- short beforePosX, short beforePosY)
- {
- // ----- Get the pen position before drawing -----
- FW_CPlatformPoint afterPoint;
- ::GetPen(&afterPoint);
-
- FontInfo fi;
- ::GetFontInfo(&fi);
-
- short strikeHeight = (fi.ascent * 2) / 5;
-
- device->SetPenSize(1,1);
- device->SetInGrafPort();
-
- ::MoveTo(beforePosX, beforePosY - strikeHeight);
- ::Line(afterPoint.h - beforePosX - 1, 0);
-
- // ----- Restore the pen position -----
- ::MoveTo(afterPoint.h, afterPoint.v);
- }
-
- #endif
-
-