void SimpleSurface::applyFilter (Surface *inSrc, const Rect &inRect, ImagePoint inOffset, Filter *inFilter) { if (!mBase) return; FilterList f; f.push_back (inFilter); Rect src_rect (inRect.w, inRect.h); Rect dest = GetFilteredObjectRect (f, src_rect); inSrc->IncRef (); Surface *result = FilterBitmap (f, inSrc, src_rect, dest, false, ImagePoint (inRect.x, inRect.y)); dest.Translate (inOffset.x, inOffset.y); src_rect = Rect (0, 0, result->Width (), result->Height ()); int dx = dest.x; int dy = dest.y; dest = dest.Intersect (Rect (0, 0, mWidth, mHeight)); dest.Translate (-dx, -dy); dest = dest.Intersect (src_rect); dest.Translate (dx, dy); int bpp = BytesPP (); RenderTarget t = BeginRender (dest, false); //printf("Copy back @ %d,%d %dx%d + (%d,%d)\n", dest.x, dest.y, t.Width(), t.Height(), dx, dy); for (int y = 0; y < t.Height (); y++) memcpy ((void *)(t.Row (y + dest.y) + ((dest.x) * bpp)), result->Row (y - dy) - (dx * bpp), dest.w * bpp); EndRender (); result->DecRef (); }
PRectangle CallTip::CallTipStart(int pos, Point pt, int textHeight, const char *defn, const char *faceName, int size, int codePage_, int characterSet, int technology, Window &wParent) { clickPlace = 0; val = defn; codePage = codePage_; Surface *surfaceMeasure = Surface::Allocate(technology); if (!surfaceMeasure) return PRectangle(); surfaceMeasure->Init(wParent.GetID()); surfaceMeasure->SetUnicodeMode(SC_CP_UTF8 == codePage); surfaceMeasure->SetDBCSMode(codePage); startHighlight = 0; endHighlight = 0; inCallTipMode = true; posStartCallTip = pos; XYPOSITION deviceHeight = static_cast<XYPOSITION>(surfaceMeasure->DeviceHeightFont(size)); FontParameters fp(faceName, deviceHeight / SC_FONT_SIZE_MULTIPLIER, SC_WEIGHT_NORMAL, false, 0, technology, characterSet); font.Create(fp); // Look for multiple lines in the text // Only support \n here - simply means container must avoid \r! int numLines = 1; const char *newline; const char *look = val.c_str(); rectUp = PRectangle(0,0,0,0); rectDown = PRectangle(0,0,0,0); offsetMain = insetX; // changed to right edge of any arrows int width = PaintContents(surfaceMeasure, false) + insetX; while ((newline = strchr(look, '\n')) != NULL) { look = newline + 1; numLines++; } lineHeight = RoundXYPosition(surfaceMeasure->Height(font)); // The returned // rectangle is aligned to the right edge of the last arrow encountered in // the tip text, else to the tip text left edge. int height = lineHeight * numLines - static_cast<int>(surfaceMeasure->InternalLeading(font)) + borderHeight * 2; delete surfaceMeasure; if (above) { return PRectangle(pt.x - offsetMain, pt.y - verticalOffset - height, pt.x + width - offsetMain, pt.y - verticalOffset); } else { return PRectangle(pt.x - offsetMain, pt.y + verticalOffset + textHeight, pt.x + width - offsetMain, pt.y + verticalOffset + textHeight + height); } }
void FontRealised::Realise(Surface &surface, int zoomLevel) { PLATFORM_ASSERT(fontName); sizeZoomed = size + zoomLevel; if (sizeZoomed <= 2) // Hangs if sizeZoomed <= 1 sizeZoomed = 2; int deviceHeight = surface.DeviceHeightFont(sizeZoomed); font.Create(fontName, characterSet, deviceHeight, bold, italic, extraFontFlag); ascent = surface.Ascent(font); descent = surface.Descent(font); externalLeading = surface.ExternalLeading(font); lineHeight = surface.Height(font); aveCharWidth = surface.AverageCharWidth(font); spaceWidth = surface.WidthChar(font, ' '); if (frNext) { frNext->Realise(surface, zoomLevel); } }
bool Render(const RenderTarget &inTarget, const RenderState &inState) { Surface *s = mFill->bitmapData; double bmp_scale_x = 1.0/s->Width(); double bmp_scale_y = 1.0/s->Height(); // Todo:skew bool is_stretch = (inState.mTransform.mMatrix->m00!=1.0 || inState.mTransform.mMatrix->m11!=1.0) && ( inState.mTransform.mMatrix->m00 > 0 && inState.mTransform.mMatrix->m11 > 0 ); for(int i=0; i<mTileData.size(); i++) { TileData &data= mTileData[i]; BlendMode blend = data.mHasColour ? ( mBlendMode==bmAdd ? bmTintedAdd : bmTinted ): mBlendMode; UserPoint corner(data.mPos); UserPoint pos = inState.mTransform.mMatrix->Apply(corner.x,corner.y); if (s->Format()==pfAlpha && !is_stretch && mBlendMode==bmNormal && data.mHasColour /* integer co-ordinate?*/ ) { unsigned int col = inState.mColourTransform->Transform(data.mColour|0xff000000); s->BlitTo(inTarget, data.mRect, (int)(pos.x), (int)(pos.y), blend, 0, col); } else if ( (is_stretch || data.mHasTrans) ) { // Can use stretch if there is no skew and no colour transform... if (!data.mHasColour && (!data.mHasTrans) && mBlendMode==bmNormal ) { UserPoint p0 = pos; pos = inState.mTransform.mMatrix->Apply(corner.x+data.mRect.w,corner.y+data.mRect.h); s->StretchTo(inTarget, data.mRect, DRect(p0.x,p0.y,pos.x,pos.y,true)); } else { int tile_alpha = 256; bool just_alpha = (data.mHasColour) && ((data.mColour&0x00ffffff ) == 0x00ffffff); if (data.mHasColour && mBlendMode==bmNormal) { tile_alpha = data.mColour>>24; if (tile_alpha>0) tile_alpha++; } // Create alpha mask... UserPoint p[4]; p[0] = inState.mTransform.mMatrix->Apply(corner.x,corner.y); if (data.mHasTrans) { p[1] = inState.mTransform.mMatrix->Apply( corner.x + data.mRect.w*data.mTransX.x, corner.y + data.mRect.w*data.mTransY.x); p[2] = inState.mTransform.mMatrix->Apply( corner.x + data.mRect.w*data.mTransX.x + data.mRect.h*data.mTransX.y, corner.y + data.mRect.w*data.mTransY.x + data.mRect.h*data.mTransY.y ); p[3] = inState.mTransform.mMatrix->Apply( corner.x + data.mRect.h*data.mTransX.y, corner.y + data.mRect.h*data.mTransY.y ); } else { p[1] = inState.mTransform.mMatrix->Apply(corner.x+data.mRect.w,corner.y); p[2] = inState.mTransform.mMatrix->Apply(corner.x+data.mRect.w,corner.y+data.mRect.h); p[3] = inState.mTransform.mMatrix->Apply(corner.x,corner.y+data.mRect.h); } Extent2DF extent; extent.Add(p[0]); extent.Add(p[1]); extent.Add(p[2]); extent.Add(p[3]); // Get bounding pixel rect Rect rect = inState.mTransform.GetTargetRect(extent); // Intersect with clip rect ... Rect visible_pixels = rect.Intersect(inState.mClipRect); if (!visible_pixels.HasPixels()) continue; Rect alpha_rect(visible_pixels); bool offscreen_buffer = mBlendMode!=bmNormal; if (offscreen_buffer) { for(int i=0; i<4; i++) { p[i].x -= visible_pixels.x; p[i].y -= visible_pixels.y; } alpha_rect.x -= visible_pixels.x; alpha_rect.y -= visible_pixels.y; } int aa = 1; SpanRect *span = new SpanRect(alpha_rect,aa); for(int i=0; i<4; i++) span->Line00( Fixed10( p[i].x, p[i].y ), Fixed10( p[(i+1)&3].x, p[(i+1)&3].y) ); AlphaMask *alpha = span->CreateMask(inState.mTransform,tile_alpha); delete span; float uvt[6]; uvt[0] = (data.mRect.x) * bmp_scale_x; uvt[1] = (data.mRect.y) * bmp_scale_y; uvt[2] = (data.mRect.x + data.mRect.w) * bmp_scale_x; uvt[3] = (data.mRect.y) * bmp_scale_y; uvt[4] = (data.mRect.x + data.mRect.w) * bmp_scale_x; uvt[5] = (data.mRect.y + data.mRect.h) * bmp_scale_y; mFiller->SetMapping(p,uvt,2); // Can render straight to surface .... if (!offscreen_buffer) { if (s->Format()==pfAlpha) { if (data.mHasColour) { ARGB col = inState.mColourTransform->Transform(data.mColour|0xff000000); mFiller->SetTint(col); } mFiller->Fill(*alpha,0,0,inTarget,inState); } else if (data.mHasTrans && !just_alpha) { ColorTransform buf; RenderState col_state(inState); ColorTransform tint; tint.redMultiplier = ((data.mColour) & 0xff) * one_on_255; tint.greenMultiplier = ((data.mColour>>8) & 0xff) * one_on_255; tint.blueMultiplier = ((data.mColour>>16) & 0xff) * one_on_255; col_state.CombineColourTransform(inState, &tint, &buf); mFiller->Fill(*alpha,0,0,inTarget,col_state); } else mFiller->Fill(*alpha,0,0,inTarget,inState); } else {
bool Render(const RenderTarget &inTarget, const RenderState &inState) { #define orthoTol 1e-6 Surface *s = mFill->bitmapData; double bmp_scale_x = 1.0/s->Width(); double bmp_scale_y = 1.0/s->Height(); bool is_base_ortho = fabs(inState.mTransform.mMatrix->m01)< orthoTol && fabs(inState.mTransform.mMatrix->m10)< orthoTol; float sx = inState.mTransform.mMatrix->m00; float sy = inState.mTransform.mMatrix->m11; bool is_base_identity = is_base_ortho && fabs(sx-1.0)<orthoTol && fabs(sy-1.0)<orthoTol; //int blits = 0; //int stretches = 0; //int renders = 0; for(int i=0;i<mTileData.size();i++) { TileData &data= mTileData[i]; BlendMode blend = data.mHasColour ? ( mBlendMode==bmAdd ? bmTintedAdd : bmTinted ): mBlendMode; UserPoint corner(data.mPos); UserPoint pos = inState.mTransform.mMatrix->Apply(corner.x,corner.y); bool is_ortho = is_base_ortho && (!data.mHasTrans || fabs(data.mTransX.y)<orthoTol); bool is_identity = data.mHasTrans ? is_ortho && fabs(sx*data.mTransX.x-1.0)<orthoTol && fabs(sy*data.mTransY.y-1)<orthoTol : is_base_identity; if ( !is_identity ) { // Can use stretch if there is no skew and no colour transform... if (!data.mHasColour && mBlendMode==bmNormal && is_ortho ) { UserPoint p0 = pos; if (data.mHasTrans) pos = inState.mTransform.mMatrix->Apply(corner.x+data.mRect.w*data.mTransX.x, corner.y+data.mRect.h*data.mTransY.y); else pos = inState.mTransform.mMatrix->Apply(corner.x+data.mRect.w,corner.y+data.mRect.h); s->StretchTo(inTarget, data.mRect, DRect(p0.x,p0.y,pos.x,pos.y,true)); //stretches++; } else { //renders++; int tile_alpha = 256; bool just_alpha = (data.mHasColour) && ((data.mColour&0x00ffffff ) == 0x00ffffff); if (data.mHasColour && mBlendMode==bmNormal) { tile_alpha = data.mColour>>24; if (tile_alpha>0) tile_alpha++; } // Create alpha mask... UserPoint p[4]; p[0] = inState.mTransform.mMatrix->Apply(corner.x,corner.y); if (data.mHasTrans) { p[1] = inState.mTransform.mMatrix->Apply( corner.x + data.mRect.w*data.mTransX.x, corner.y + data.mRect.w*data.mTransY.x); p[2] = inState.mTransform.mMatrix->Apply( corner.x + data.mRect.w*data.mTransX.x + data.mRect.h*data.mTransX.y, corner.y + data.mRect.w*data.mTransY.x + data.mRect.h*data.mTransY.y ); p[3] = inState.mTransform.mMatrix->Apply( corner.x + data.mRect.h*data.mTransX.y, corner.y + data.mRect.h*data.mTransY.y ); } else { p[1] = inState.mTransform.mMatrix->Apply(corner.x+data.mRect.w,corner.y); p[2] = inState.mTransform.mMatrix->Apply(corner.x+data.mRect.w,corner.y+data.mRect.h); p[3] = inState.mTransform.mMatrix->Apply(corner.x,corner.y+data.mRect.h); } Extent2DF extent; extent.Add(p[0]); extent.Add(p[1]); extent.Add(p[2]); extent.Add(p[3]); // Get bounding pixel rect Rect rect = inState.mTransform.GetTargetRect(extent); // Intersect with clip rect ... Rect visible_pixels = rect.Intersect(inState.mClipRect); if (!visible_pixels.HasPixels()) continue; Rect alpha_rect(visible_pixels); bool offscreen_buffer = mBlendMode!=bmNormal; if (offscreen_buffer) { for(int i=0;i<4;i++) { p[i].x -= visible_pixels.x; p[i].y -= visible_pixels.y; } alpha_rect.x -= visible_pixels.x; alpha_rect.y -= visible_pixels.y; } int aa = 1; SpanRect *span = new SpanRect(alpha_rect,aa); // ToImageAA - add 0.5 offset for(int i=0;i<4;i++) span->Line00( Fixed10( p[i].x + 0.5, p[i].y + 0.5 ), Fixed10( p[(i+1)&3].x + 0.5, p[(i+1)&3].y + 0.5) ); AlphaMask *alpha = span->CreateMask(inState.mTransform,tile_alpha); delete span; float uvt[6]; uvt[0] = (data.mRect.x) * bmp_scale_x; uvt[1] = (data.mRect.y) * bmp_scale_y; uvt[2] = (data.mRect.x + data.mRect.w) * bmp_scale_x; uvt[3] = (data.mRect.y) * bmp_scale_y; uvt[4] = (data.mRect.x + data.mRect.w) * bmp_scale_x; uvt[5] = (data.mRect.y + data.mRect.h) * bmp_scale_y; mFiller->SetMapping(p,uvt,2); // Can render straight to surface .... if (!offscreen_buffer) { if (s->Format()==pfAlpha) { if (data.mHasColour) { ARGB col = inState.mColourTransform->Transform(data.mColour|0xff000000); mFiller->SetTint(col); } mFiller->Fill(*alpha,0,0,inTarget,inState); } else if (data.mHasTrans && !just_alpha) { ColorTransform buf; RenderState col_state(inState); ColorTransform tint; tint.redMultiplier = ((data.mColour) & 0xff) * one_on_255; tint.greenMultiplier = ((data.mColour>>8) & 0xff) * one_on_255; tint.blueMultiplier = ((data.mColour>>16) & 0xff) * one_on_255; col_state.CombineColourTransform(inState, &tint, &buf); mFiller->Fill(*alpha,0,0,inTarget,col_state); } else mFiller->Fill(*alpha,0,0,inTarget,inState); } else {