void KPR_canvasPattern_setStyle(xsMachine *the) { FskCanvas2dContext ctx = xsGetHostData(xsArg(0)); UInt32 repetition = kFskCanvas2dPatternRepeat; FskConstBitmap bitmap = NULL; Boolean owned = false; xsVars(1); xsVar(0) = xsGet(xsThis, xsID("repetition")); if (xsTest(xsVar(0))) { xsStringValue it = xsToString(xsVar(0)); if (!FskStrCompare(it, "no-repeat")) repetition = kFskCanvas2dPatternRepeatNone; else if (!FskStrCompare(it, "repeat-x")) repetition = kFskCanvas2dPatternRepeatX; else if (!FskStrCompare(it, "repeat-y")) repetition = kFskCanvas2dPatternRepeatY; else if (!FskStrCompare(it, "repeat")) repetition = kFskCanvas2dPatternRepeat; else xsError(kFskErrInvalidParameter); } xsVar(0) = xsGet(xsThis, xsID("image")); if (xsIsInstanceOf(xsVar(0), xsGet(xsGet(xsGlobal, xsID_KPR), xsID_texture))) { KprTexture texture = xsGetHostData(xsVar(0)); bitmap = KprTextureGetBitmap(texture, NULL, &owned); } else { KprContent content = xsGetHostData(xsVar(0)); bitmap = (*content->dispatch->getBitmap)(content, NULL, &owned); } if (!bitmap) xsError(kFskErrInvalidParameter); if (xsTest(xsArg(1))) FskCanvas2dSetStrokeStylePattern(ctx, repetition, bitmap); else FskCanvas2dSetFillStylePattern(ctx, repetition, bitmap); if (!owned) FskBitmapDispose((FskBitmap)bitmap); }
// drawing images void KPR_canvasRenderingContext2D_drawImage(xsMachine *the) { FskCanvas2dContext ctx = xsGetHostData(xsThis); xsIntegerValue c = xsToInteger(xsArgc); FskConstCanvas cnv = NULL; FskBitmap bitmap = NULL; Boolean owned = false; xsVars(1); if (xsIsInstanceOf(xsArg(0), xsGet(xsGet(xsGlobal, xsID_KPR), xsID_texture))) { KprTexture texture = xsGetHostData(xsArg(0)); bitmap = KprTextureGetBitmap(texture, NULL, &owned); } else { KprContent content = xsGetHostData(xsArg(0)); if (content->dispatch == &KprCanvasDispatchRecord) cnv = ((KprCanvas)content)->cnv; else bitmap = (*content->dispatch->getBitmap)(content, NULL, &owned); } if (!cnv && !bitmap) xsError(kFskErrInvalidParameter); if (c > 8) { xsNumberValue sx = xsToNumber(xsArg(1)); xsNumberValue sy = xsToNumber(xsArg(2)); xsNumberValue sw = xsToNumber(xsArg(3)); xsNumberValue sh = xsToNumber(xsArg(4)); xsNumberValue dx = xsToNumber(xsArg(5)); xsNumberValue dy = xsToNumber(xsArg(6)); xsNumberValue dw = xsToNumber(xsArg(7)); xsNumberValue dh = xsToNumber(xsArg(8)); if (cnv) FskCanvas2dDrawSubScaledCanvas2d(ctx, cnv, sx, sy, sw, sh, dx, dy, dw, dh); else FskCanvas2dDrawSubScaledBitmap(ctx, bitmap, sx, sy, sw, sh, dx, dy, dw, dh); } else if (c > 4) { xsNumberValue dx = xsToNumber(xsArg(1)); xsNumberValue dy = xsToNumber(xsArg(2)); xsNumberValue dw = xsToNumber(xsArg(3)); xsNumberValue dh = xsToNumber(xsArg(4)); if (cnv) FskCanvas2dDrawScaledCanvas2d(ctx, cnv, dx, dy, dw, dh); else FskCanvas2dDrawScaledBitmap(ctx, bitmap, dx, dy, dw, dh); } else { xsNumberValue dx = xsToNumber(xsArg(1)); xsNumberValue dy = xsToNumber(xsArg(2)); if (cnv) FskCanvas2dDrawCanvas2d(ctx, cnv, dx, dy); else FskCanvas2dDrawBitmap(ctx, bitmap, dx, dy); } if (!owned) FskBitmapDispose(bitmap); }
FskErr KplScreenDisposeBitmap(KplBitmap bitmap) { FskErr err = kFskErrNone; KplScreen screen = gKplScreen; if (bitmap != screen->bitmap) return kFskErrOperationFailed; if (screen->thread) { // KplScreenEventWakeUp(); FskThreadJoin(screen->thread); screen->thread = NULL; } #if SUPPORT_FLIP_THREAD if (screen->flipThread) { KplScreenUnlockBitmap(bitmap); FskThreadJoin(screen->flipThread); screen->flipThread = NULL; } #endif if (screen->fbfd == -1) { FskMemPtrDispose(screen->framebuffer); } else { munmap(screen->framebuffer, screen->finfo.smem_len); close(screen->fbfd); } FskBitmapDispose(screen->touchDown); #if SUPPORT_FLIP_THREAD FskSemaphoreDispose(screen->flipSemaphore); #endif FskMemPtrDispose(screen); terminateLinuxInput(); gKplScreen = NULL; return err; }
FskErr winTextBox(FskTextEngineState state, FskBitmap bits, const char *text, UInt32 textLen, FskConstRectangle bounds, FskConstRectangleFloat boundsFloat, FskConstRectangle clipRect, FskConstColorRGBA color, UInt32 blendLevel, UInt32 textSize, UInt32 textStyle, UInt16 hAlign, UInt16 vAlign, FskFixed textExtra, const char *fontName, FskTextFormatCache formatCacheIn) { FskTextFormatCacheGDI formatCache = (FskTextFormatCacheGDI)formatCacheIn; RECT r; UINT flags = DT_SINGLELINE | DT_NOPREFIX | ((kFskTextTruncateEnd & textStyle) ? DT_END_ELLIPSIS : 0); Boolean direct = (blendLevel >= 255) && (NULL != bits->hbmp) && !((kFskTextOutline | kFskTextOutlineHeavy) & textStyle) && !bits->hasAlpha; FskBitmap scratchBits = NULL; HFONT font; HDC dc = direct ? bits->hdc : state->dc; HGDIOBJ saveFont; FskRectangleRecord clip; unsigned char scratchBuffer[256]; int saveCharExtra; // combine bounds and clip to total clip if (NULL == clipRect) { clip = *bounds; } else { if (false == FskRectangleIntersect(clipRect, bounds, &clip)) return kFskErrNone; } if (direct) { if (clipRect) IntersectClipRect(dc, clipRect->x, clipRect->y, clipRect->x + clipRect->width, clipRect->y + clipRect->height); SetRect(&r, bounds->x, bounds->y, bounds->x + bounds->width, bounds->y + bounds->height); SetTextColor(dc, RGB(color->r, color->g, color->b)); } else { FskErr err; const UInt32 kFskTextOffscreenFormat = kFskBitmapFormat24BGR; /* Negative width below indicates that we want a native bitmap */ err = FskBitmapNew(-bounds->width, bounds->height, kFskTextOffscreenFormat, &scratchBits); if (kFskErrNone == err) SetRect(&r, 0, 0, bounds->width, bounds->height); else { FskRectangleRecord b; err = winTextGetBounds(state, bits, text, textLen, textSize, textStyle, textExtra, fontName, &b, NULL, formatCacheIn); if (err) return err; err = FskBitmapNew(-b.width, b.height, kFskTextOffscreenFormat, &scratchBits); if (err) return err; SetRect(&r, 0, 0, b.width, b.height); } dc = scratchBits->hdc; SetTextColor(dc, RGB(255, 255, 255)); } if (NULL == formatCache) saveFont = syncFont(textSize, textStyle, fontName, &font, state); else saveFont = SelectObject(dc, formatCache->font); saveCharExtra = SetTextCharacterExtra(dc, textExtra >> 16); #if 0 switch (hAlign) { case kFskTextAlignLeft: default: flags |= DT_LEFT; break; case kFskTextAlignCenter: flags |= DT_CENTER; break; case kFskTextAlignRight: flags |= DT_RIGHT; break; } switch (vAlign) { case kFskTextAlignTop: default: flags |= DT_TOP; break; case kFskTextAlignCenter: flags |= DT_VCENTER; break; case kFskTextAlignBottom: flags |= DT_BOTTOM; break; } #endif { SIZE sz; UINT align; SInt32 y; char *encodedText = (char *)scratchBuffer; UInt32 encodedTextLen = sizeof(scratchBuffer); if (kFskErrNone != FskTextUTF8ToUnicode16NENoAlloc(text, textLen, (UInt16 *)scratchBuffer, &encodedTextLen)) { if (kFskErrNone != FskMemPtrNew(encodedTextLen, &encodedText)) { FskBitmapDispose(scratchBits); goto done; } FskTextUTF8ToUnicode16NENoAlloc(text, textLen, (UInt16 *)encodedText, &encodedTextLen); } encodedTextLen >>= 1; remapForMicrosoft((UInt16 *)encodedText, encodedTextLen); if (kFskTextTruncateCenter & textStyle) { // work hard to truncate the center, since Windows doesn't support this directly SIZE size; int *widths; if (kFskErrNone == FskMemPtrNew(sizeof(int) * encodedTextLen, (FskMemPtr *)&widths)) { int maxC, i, fitWidth = (r.right - r.left); GetTextExtentExPointW(dc, (WCHAR *)encodedText, encodedTextLen, 32768, &maxC, widths, &size); if (size.cx > fitWidth) { SInt32 currentWidth = size.cx; SInt32 truncBegin, truncEnd; WCHAR ellipsis = 0x2026; SIZE ellipsisSize; UInt16 *uniChars = (UInt16 *)encodedText; for (i = encodedTextLen - 1; i > 0; i--) widths[i] -= widths[i - 1]; GetTextExtentPoint32W(dc, (LPWSTR)&ellipsis, 1, &ellipsisSize); //@@ could use ellipsisWidth in cache here fitWidth -= ellipsisSize.cx; if (fitWidth > 0) { Boolean phase = true; // start towards the end truncBegin = truncEnd = encodedTextLen / 2; while ((currentWidth > fitWidth) && ((truncEnd - truncBegin) != encodedTextLen)) { if (phase) { if (truncEnd < (SInt32)encodedTextLen) { currentWidth -= widths[truncEnd]; truncEnd += 1; } } else { if (0 != truncBegin) { truncBegin -= 1; currentWidth -= widths[truncBegin]; } } phase = !phase; } FskMemMove(&uniChars[truncBegin + 1], &uniChars[truncEnd], (encodedTextLen - truncEnd) * 2); uniChars[truncBegin] = ellipsis; encodedTextLen -= (truncEnd - truncBegin); encodedTextLen += 1; flags &= ~DT_END_ELLIPSIS; } } FskMemPtrDispose(widths); } } #if 0 DrawTextW(dc, (LPWSTR)encodedText, encodedTextLen, &r, flags); #else if (kFskTextTruncateEnd & textStyle) { int fitChars; int stackWidths[256], *widths, width = r.right - r.left; WCHAR ellipsis = 0x2026; SIZE ellipsisSz; if (encodedTextLen < 256) widths = stackWidths; else { if (kFskErrNone != FskMemPtrNew(sizeof(int) * encodedTextLen, (FskMemPtr *)&widths)) { widths = stackWidths; encodedTextLen = 256; } } GetTextExtentExPointW(dc, (WCHAR *)encodedText, encodedTextLen, width, &fitChars, widths, &sz); if ((UInt32)fitChars < encodedTextLen) { // remove trailing white space if (formatCache) { if (!formatCache->haveEllipsisWidth) { GetTextExtentExPointW(dc, (WCHAR *)&ellipsis, 1, 0, NULL, NULL, &ellipsisSz); formatCache->haveEllipsisWidth = true; formatCache->ellipsisWidth = ellipsisSz.cx; } else ellipsisSz.cx = formatCache->ellipsisWidth; } else GetTextExtentExPointW(dc, (WCHAR *)&ellipsis, 1, 0, NULL, NULL, &ellipsisSz); if (width > ellipsisSz.cx) { width -= ellipsisSz.cx; while (fitChars > 2) { UInt16 c = ((UInt16 *)encodedText)[fitChars - 2]; if ((32 != c) && (9 != c) && (0x3000 != c)) break; fitChars -= 1; } // truncate if needed to make room for the ellipsis while ((widths[fitChars - 1] > width) && (fitChars > 2)) fitChars -= 1; // add ellipsis ((UInt16 *)encodedText)[fitChars - 1] = 0x2026; // ellipsis encodedTextLen = fitChars; } else encodedTextLen = 0; } if (widths != stackWidths) FskMemPtrDispose(widths); } else { if (kFskTextAlignCenter == vAlign) GetTextExtentExPointW(dc, (WCHAR *)encodedText, encodedTextLen, 0, NULL, NULL, &sz); } if (kFskTextAlignCenter == vAlign) { y = (r.top + r.bottom - sz.cy) >> 1; align = TA_TOP; } else if (kFskTextAlignTop == vAlign) {