276 lines
7.7 KiB
C++
276 lines
7.7 KiB
C++
|
#include <bfc/platform/types.h>
|
||
|
#include <Carbon/Carbon.h>
|
||
|
#include <tataki/canvas/canvas.h>
|
||
|
#include <api/wnd/basewnd.h>
|
||
|
#include <tataki/region/api_region.h>
|
||
|
|
||
|
|
||
|
|
||
|
/* various functions that might help out
|
||
|
|
||
|
for drawSysObject:
|
||
|
HIThemeDrawButton
|
||
|
HIThemeDrawTitleBarWidget for minimize, maximize, exit
|
||
|
*/
|
||
|
|
||
|
inline float QuartzBlue(RGB32 color)
|
||
|
{
|
||
|
unsigned char *pixel = (unsigned char *)&color;
|
||
|
return pixel[0] / 255.f;
|
||
|
}
|
||
|
|
||
|
inline float QuartzGreen(RGB32 color)
|
||
|
{
|
||
|
unsigned char *pixel = (unsigned char *)&color;
|
||
|
return pixel[1] / 255.f;
|
||
|
|
||
|
}
|
||
|
|
||
|
inline float QuartzRed(RGB32 color)
|
||
|
{
|
||
|
unsigned char *pixel = (unsigned char *)&color;
|
||
|
return pixel[2] / 255.f;
|
||
|
|
||
|
}
|
||
|
|
||
|
inline float QuartzAlpha(RGB32 color)
|
||
|
{
|
||
|
unsigned char *pixel = (unsigned char *)&color;
|
||
|
return pixel[3] / 255.f;
|
||
|
|
||
|
}
|
||
|
|
||
|
Canvas::Canvas(CGrafPtr _context)
|
||
|
{
|
||
|
|
||
|
}
|
||
|
|
||
|
void Canvas::fillRect(const RECT *r, ARGB32 color)
|
||
|
{
|
||
|
CGContextSetRGBFillColor(context,
|
||
|
QuartzRed(color), // red
|
||
|
QuartzGreen(color), // green
|
||
|
QuartzBlue(color), // blue
|
||
|
QuartzAlpha(color) // alpha
|
||
|
);
|
||
|
|
||
|
HIRect rect = HIRectFromRECT(r);
|
||
|
CGContextFillRect(context, rect);
|
||
|
}
|
||
|
|
||
|
void Canvas::fillRgn(api_region *r, ARGB32 color)
|
||
|
{
|
||
|
CGContextSetRGBFillColor(context,
|
||
|
QuartzRed(color), // red
|
||
|
QuartzGreen(color), // green
|
||
|
QuartzBlue(color), // blue
|
||
|
QuartzAlpha(color) // alpha
|
||
|
);
|
||
|
|
||
|
HIShapeRef shape = r->getOSHandle();
|
||
|
HIShapeReplacePathInCGContext(shape, context);
|
||
|
CGContextFillPath(context);
|
||
|
}
|
||
|
|
||
|
void Canvas::blit(int srcx, int srcy, Canvas *dest, int dstx, int dsty, int dstw, int dsth)
|
||
|
{
|
||
|
// clip dest
|
||
|
// Create CGImage from context
|
||
|
// CGContextDrawImage
|
||
|
}
|
||
|
|
||
|
HDC Canvas::getHDC()
|
||
|
{
|
||
|
return context;
|
||
|
}
|
||
|
|
||
|
void Canvas::selectClipRgn(api_region *r)
|
||
|
{
|
||
|
if (r)
|
||
|
{
|
||
|
HIShapeRef shape = r->getOSHandle();
|
||
|
HIShapeReplacePathInCGContext(shape, context);
|
||
|
CGContextClip(context);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
CGContextClipToRect(context, CGRectInfinite);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
void Canvas::stretchblit(int srcx, int srcy, int srcw, int srch, Canvas *dest, int dstx, int dsty, int dstw, int dsth)
|
||
|
{
|
||
|
// Create CGImage from context
|
||
|
// CGContextDrawImage
|
||
|
}
|
||
|
|
||
|
void Canvas::textOut(int x, int y, const wchar_t *txt, const Wasabi::FontInfo *fontInfo)
|
||
|
{
|
||
|
// TODO: turn this code into a svc_fontI, and use api_font here instead
|
||
|
size_t len = wcslen(txt);
|
||
|
UniChar *unistr = (UniChar *)malloc((len + 1) * sizeof(UniChar));
|
||
|
UniChar *copy = unistr;
|
||
|
while (*txt)
|
||
|
*copy++=*txt++;
|
||
|
*copy=0;
|
||
|
|
||
|
ATSUStyle style;
|
||
|
ATSUCreateStyle(&style);
|
||
|
|
||
|
CGContextSaveGState(context);
|
||
|
CGContextSetRGBFillColor(context,
|
||
|
QuartzRed(fontInfo->color), // red
|
||
|
QuartzGreen(fontInfo->color), // green
|
||
|
QuartzBlue(fontInfo->color), // blue
|
||
|
QuartzAlpha(fontInfo->color) // alpha
|
||
|
);
|
||
|
|
||
|
ATSUTextLayout layout;
|
||
|
ATSUCreateTextLayout(&layout);
|
||
|
|
||
|
ATSUSetTextPointerLocation(layout, unistr, kATSUFromTextBeginning, kATSUToTextEnd, len);
|
||
|
|
||
|
ATSUSetRunStyle(layout, style, kATSUFromTextBeginning, kATSUToTextEnd);
|
||
|
|
||
|
Rect imageRect;
|
||
|
ATSUMeasureTextImage(layout, kATSUFromTextBeginning, kATSUToTextEnd, 0, 0, &imageRect);
|
||
|
y-=(imageRect.bottom - imageRect.top);
|
||
|
CGContextScaleCTM(context, 1.0, -1.0);
|
||
|
|
||
|
ATSUAttributeTag tags[] = {kATSUCGContextTag};
|
||
|
ATSUAttributeValuePtr values[] = {&context};
|
||
|
ByteCount sizes[] = {sizeof(CGContextRef)};
|
||
|
ATSUSetLayoutControls(layout, 1, tags, sizes, values);
|
||
|
ATSUDrawText(layout, kATSUFromTextBeginning, kATSUToTextEnd, FloatToFixed(x), FloatToFixed(y));
|
||
|
ATSUDisposeTextLayout(layout);
|
||
|
ATSUDisposeStyle(style);
|
||
|
CGContextRestoreGState(context);
|
||
|
free(unistr);
|
||
|
}
|
||
|
|
||
|
void Canvas::drawSysObject(const RECT *r, int sysobj, int alpha)
|
||
|
{
|
||
|
#warning TODO
|
||
|
using namespace DrawSysObj;
|
||
|
switch(sysobj)
|
||
|
{
|
||
|
case OSBUTTON:
|
||
|
{
|
||
|
HIRect buttonRect = HIRectFromRECT(r);
|
||
|
HIThemeButtonDrawInfo buttonDrawInfo;
|
||
|
buttonDrawInfo.version=0;
|
||
|
buttonDrawInfo.state = kThemeStateActive;
|
||
|
buttonDrawInfo.kind = kThemePushButton;
|
||
|
buttonDrawInfo.value = kThemeButtonOn;
|
||
|
buttonDrawInfo.adornment = kThemeAdornmentNone;
|
||
|
buttonDrawInfo.animation.time.start = 0;
|
||
|
buttonDrawInfo.animation.time.current=0;
|
||
|
HIThemeDrawButton(&buttonRect, &buttonDrawInfo, context, /*kHIThemeOrientationNormal*/kHIThemeOrientationInverted, 0);
|
||
|
}
|
||
|
break;
|
||
|
case OSBUTTON_PUSHED:
|
||
|
{
|
||
|
HIRect buttonRect = HIRectFromRECT(r);
|
||
|
HIThemeButtonDrawInfo buttonDrawInfo;
|
||
|
buttonDrawInfo.version=0;
|
||
|
buttonDrawInfo.state = kThemeStatePressed;
|
||
|
buttonDrawInfo.kind = kThemePushButton;
|
||
|
buttonDrawInfo.value = kThemeButtonOn;
|
||
|
buttonDrawInfo.adornment = kThemeAdornmentNone;
|
||
|
buttonDrawInfo.animation.time.start = 0;
|
||
|
buttonDrawInfo.animation.time.current=0;
|
||
|
HIThemeDrawButton(&buttonRect, &buttonDrawInfo, context, /*kHIThemeOrientationNormal*/kHIThemeOrientationInverted, 0);
|
||
|
}
|
||
|
break;
|
||
|
case OSBUTTON_DISABLED:
|
||
|
{
|
||
|
HIRect buttonRect = HIRectFromRECT(r);
|
||
|
HIThemeButtonDrawInfo buttonDrawInfo;
|
||
|
buttonDrawInfo.version=0;
|
||
|
buttonDrawInfo.state = kThemeStateInactive;
|
||
|
buttonDrawInfo.kind = kThemePushButton;
|
||
|
buttonDrawInfo.value = kThemeButtonOn;
|
||
|
buttonDrawInfo.adornment = kThemeAdornmentNone;
|
||
|
buttonDrawInfo.animation.time.start = 0;
|
||
|
buttonDrawInfo.animation.time.current=0;
|
||
|
HIThemeDrawButton(&buttonRect, &buttonDrawInfo, context, /*kHIThemeOrientationNormal*/kHIThemeOrientationInverted, 0);
|
||
|
}
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
void Canvas::getTextExtent(const wchar_t *text, int *w, int *h, const Wasabi::FontInfo *fontInfo)
|
||
|
{
|
||
|
// TODO: turn this code into a svc_fontI, and use api_font here instead
|
||
|
size_t len = wcslen(text);
|
||
|
UniChar *unistr = (UniChar *)malloc((len + 1) * sizeof(UniChar));
|
||
|
UniChar *copy = unistr;
|
||
|
while (*text)
|
||
|
*copy++=*text++;
|
||
|
*copy=0;
|
||
|
|
||
|
ATSUStyle style;
|
||
|
ATSUCreateStyle(&style);
|
||
|
|
||
|
ATSUTextLayout layout;
|
||
|
ATSUCreateTextLayout(&layout);
|
||
|
|
||
|
ATSUSetTextPointerLocation(layout, unistr, kATSUFromTextBeginning, kATSUToTextEnd, len);
|
||
|
|
||
|
ATSUSetRunStyle(layout, style, kATSUFromTextBeginning, kATSUToTextEnd);
|
||
|
|
||
|
Rect imageRect;
|
||
|
ATSUMeasureTextImage(layout, kATSUFromTextBeginning, kATSUToTextEnd, 0, 0, &imageRect);
|
||
|
*h=(imageRect.bottom - imageRect.top);
|
||
|
*w = (imageRect.right - imageRect.left);
|
||
|
|
||
|
ATSUDisposeTextLayout(layout);
|
||
|
ATSUDisposeStyle(style);
|
||
|
free(unistr);
|
||
|
}
|
||
|
|
||
|
void Canvas::textOutCentered(RECT *r, const wchar_t *txt, const Wasabi::FontInfo *fontInfo)
|
||
|
{
|
||
|
textOut(r->left, r->top, txt, fontInfo);
|
||
|
}
|
||
|
|
||
|
|
||
|
#define CBCLASS Canvas
|
||
|
START_DISPATCH;
|
||
|
CB(GETHDC, getHDC);
|
||
|
END_DISPATCH;
|
||
|
#undef CBCLASS
|
||
|
|
||
|
BaseCloneCanvas::BaseCloneCanvas(api_canvas *cloner)
|
||
|
{
|
||
|
if (cloner != NULL) clone(cloner);
|
||
|
}
|
||
|
|
||
|
int BaseCloneCanvas::clone(api_canvas *cloner)
|
||
|
{
|
||
|
ASSERTPR(context == NULL, "can't clone twice");
|
||
|
context = cloner->getHDC();
|
||
|
CGContextRetain(context);
|
||
|
// bits = cloner->getBits();
|
||
|
// cloner->getDim(&width, &height, &pitch);
|
||
|
// srcwnd = cloner->getBaseWnd();
|
||
|
// cloner->getOffsets(&xoffset, &yoffset);
|
||
|
// setTextFont(cloner->getTextFont());
|
||
|
// setTextSize(cloner->getTextSize());
|
||
|
// setTextBold(cloner->getTextBold());
|
||
|
// setTextOpaque(cloner->getTextOpaque());
|
||
|
// setTextUnderline(cloner->getTextUnderline());
|
||
|
// setTextItalic(cloner->getTextItalic());
|
||
|
// setTextAlign(cloner->getTextAlign());
|
||
|
// setTextColor(cloner->getTextColor());
|
||
|
// setTextBkColor(cloner->getTextBkColor());
|
||
|
return (context != NULL);
|
||
|
}
|
||
|
|
||
|
BaseCloneCanvas::~BaseCloneCanvas()
|
||
|
{
|
||
|
CGContextRelease(context);
|
||
|
context = NULL;
|
||
|
}
|
||
|
|