1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
1.2 +++ b/os/graphics/graphicsdeviceinterface/bitgdi/sbit/TEXT.CPP Fri Jun 15 03:10:57 2012 +0200
1.3 @@ -0,0 +1,1307 @@
1.4 +// Copyright (c) 1997-2009 Nokia Corporation and/or its subsidiary(-ies).
1.5 +// All rights reserved.
1.6 +// This component and the accompanying materials are made available
1.7 +// under the terms of "Eclipse Public License v1.0"
1.8 +// which accompanies this distribution, and is available
1.9 +// at the URL "http://www.eclipse.org/legal/epl-v10.html".
1.10 +//
1.11 +// Initial Contributors:
1.12 +// Nokia Corporation - initial contribution.
1.13 +//
1.14 +// Contributors:
1.15 +//
1.16 +// Description:
1.17 +//
1.18 +
1.19 +#include <fntstore.h>
1.20 +#include <bitdraw.h>
1.21 +#include <bitstd.h>
1.22 +#include <bitdev.h>
1.23 +#include "BITPANIC.H"
1.24 +#include <shapeinfo.h>
1.25 +#include <bmalphablend.h>
1.26 +#include <bitdrawinterfaceid.h>
1.27 +#include <graphics/fbsrasterizer.h>
1.28 +#include "bitgcextradata.h"
1.29 +#include <graphics/gdi/gdiconsts.h>
1.30 +#include <graphics/gdi/gdistructs.h>
1.31 +
1.32 +
1.33 +/** Draws text at the last print position.
1.34 +
1.35 +@param aText The text string to be drawn. */
1.36 +EXPORT_C void CFbsBitGc::DrawText(const TDesC& aText)
1.37 + {
1.38 + TTextParameters* param = NULL;
1.39 + DrawText(aText,param,iLastPrintPosition,ELeft,CFont::EHorizontal);
1.40 + }
1.41 +
1.42 +/** Draws text at the specified position and updates the print position.
1.43 +
1.44 +@param aText The text string to be drawn
1.45 +@param aCoords Coordinates to draw the text at. */
1.46 +EXPORT_C void CFbsBitGc::DrawText(const TDesC& aText,const TPoint& aCoords)
1.47 + {
1.48 + TTextParameters* param = NULL;
1.49 + DrawText(aText,param,aCoords,ELeft,CFont::EHorizontal);
1.50 + }
1.51 +
1.52 +
1.53 +/** Draws text clipped to the specified rectangle.
1.54 +
1.55 +@param aText The text string to be drawn
1.56 +@param aBox The clipping rectangle. */
1.57 +EXPORT_C void CFbsBitGc::DrawText(const TDesC& aText,const TRect& aBox)
1.58 + {
1.59 + TTextParameters* param = NULL;
1.60 + DrawText(aText,param,aBox);
1.61 + }
1.62 +
1.63 +
1.64 +/** Draws text clipped to the specified rectangle using a baseline offset,
1.65 +horizontal alignment and a margin.
1.66 +
1.67 +@param aText The text string to be drawn
1.68 +@param aBox The clipping rectangle.
1.69 +@param aBLOff An offset in pixels for the baseline from the normal position
1.70 + (bottom of the rectangle minus the descent of the font).
1.71 +@param aHrz Horizontal alignment option relative to the specified rectangle.
1.72 +@param aMargin Offset to add to the position as calculated using specified
1.73 + rectangle. */
1.74 +EXPORT_C void CFbsBitGc::DrawText(const TDesC& aText,const TRect& aBox,TInt aBLOff,
1.75 + TTextAlign aHrz,TInt aMargin)
1.76 + {
1.77 + TTextParameters* param = NULL;
1.78 + DrawText(aText,param,aBox,aBLOff,-1,aHrz,aMargin);
1.79 + }
1.80 +
1.81 +/** Draws text clipped to the specified rectangle.
1.82 +
1.83 +@param aText The text string to be drawn
1.84 +@param aBox The clipping rectangle. */
1.85 +EXPORT_C void CFbsBitGc::DrawText(const TDesC& aText,const TRect& aBox,
1.86 + TInt aBLOff,TInt /*aTextWidth*/,
1.87 + TTextAlign aHrz,TInt aMargin)
1.88 + {
1.89 +// aTextWidth is not used here - try to abolish this - I think it is unneeded
1.90 + TPoint p(aBox.iTl);
1.91 + p.iY += aBLOff;
1.92 + switch (aHrz)
1.93 + {
1.94 + case ELeft: p.iX += aMargin; break;
1.95 + case ERight: p.iX = aBox.iBr.iX - aMargin; break;
1.96 + case ECenter: p.iX += aBox.Width() / 2 + aMargin; break;
1.97 + }
1.98 + TTextParameters* param = NULL;
1.99 + DrawText(aText,param,p,aHrz,CFont::EHorizontal,&aBox);
1.100 + }
1.101 +
1.102 +
1.103 +/** The general DrawText routine that implements all the others.
1.104 +
1.105 +@param aText the text to be drawn
1.106 +@param aPosition the origin of the text
1.107 +@param aAlignment left, centred or right, around aPosition; not used if drawing vertically
1.108 +@param aDirection direction: left to right, right to left, or top to bottom
1.109 +@param aBox if non-null, filled before the text is drawn
1.110 +@param aTextBounds if non-null returns the bounding box of the text
1.111 +*/
1.112 +void CFbsBitGc::DrawText(const TDesC& aText,const TTextParameters* aParam,const TPoint& aPosition,TTextAlign aAlignment,
1.113 + CFont::TTextDirection aDirection,const TRect* aBox)
1.114 + {
1.115 + // sanity checks
1.116 + BG_ASSERT_ALWAYS(iDevice,EBitgdiPanicNoDevicePresent);
1.117 + BG_ASSERT_ALWAYS(iFont.Handle() != 0,EBitgdiPanicNoFontSelected);
1.118 + const CBitmapFont* bitmap_font = iFont.Address();
1.119 + BG_ASSERT_ALWAYS(bitmap_font != 0,EBitgdiPanicNoFontSelected);
1.120 +
1.121 + // anything to do?
1.122 + if (!aBox && !aText.Length())
1.123 + return;
1.124 +
1.125 + CFbsDrawDevice* drawDevice = iDevice->iDrawDevice;
1.126 +
1.127 + TRect deviceRect;
1.128 + drawDevice->GetDrawRect(deviceRect);
1.129 +
1.130 + // measure the text
1.131 + CFont::TMeasureTextInput measure_text_input;
1.132 + measure_text_input.iCharJustNum = iCharJustNum;
1.133 + measure_text_input.iCharJustExcess = iCharJustExcess;
1.134 + measure_text_input.iWordJustNum = iWordJustNum;
1.135 + measure_text_input.iWordJustExcess = iWordJustExcess;
1.136 + measure_text_input.iFlags |= CFont::TMeasureTextInput::EFVisualOrder;
1.137 + if (aParam)
1.138 + {
1.139 + BG_ASSERT_ALWAYS(aParam->iStart < aParam->iEnd ,EBitgdiPanicInvalidParameter);
1.140 + measure_text_input.iStartInputChar = aParam->iStart;
1.141 + measure_text_input.iEndInputChar = Min(aText.Length(),aParam->iEnd);
1.142 + }
1.143 + CFont::TMeasureTextOutput measure_text_output;
1.144 + const int advance = iFont.MeasureText(aText,&measure_text_input,&measure_text_output);
1.145 + TRect text_bounds = measure_text_output.iBounds;
1.146 + TInt underlineStrikeoutOffset;
1.147 +
1.148 + //this call is only needed in the case of linked fonts
1.149 + //should this pass by one structure?
1.150 + underlineStrikeoutOffset= BaselineCorrection();
1.151 +
1.152 + if (iUnderline == EUnderlineOn)
1.153 + {
1.154 + TInt underline_top = 0, underline_bottom = 0;
1.155 + TInt err = GetUnderlineMetrics(underline_top,underline_bottom);
1.156 + underline_top+=underlineStrikeoutOffset;
1.157 + underline_bottom+=underlineStrikeoutOffset;
1.158 + BG_ASSERT_DEBUG(err == KErrNone, EBitgdiPanicInvalidArg);
1.159 + text_bounds.iTl.iY = Min(text_bounds.iTl.iY,underline_top);
1.160 + text_bounds.iBr.iY = Max(text_bounds.iBr.iY,underline_bottom);
1.161 + }
1.162 + if (iStrikethrough == EStrikethroughOn)
1.163 + {
1.164 + TInt strike_top = 0,strike_bottom = 0;
1.165 + GetStrikethroughMetrics(strike_top,strike_bottom);
1.166 + strike_top+=underlineStrikeoutOffset;
1.167 + strike_bottom+=underlineStrikeoutOffset;
1.168 + text_bounds.iTl.iY = Min(text_bounds.iTl.iY,strike_top);
1.169 + text_bounds.iBr.iY = Max(text_bounds.iBr.iY,strike_bottom);
1.170 + }
1.171 + if (iUnderline == EUnderlineOn || iStrikethrough == EStrikethroughOn)
1.172 + {
1.173 + if (aDirection == CFont::EHorizontal)
1.174 + {
1.175 + text_bounds.iTl.iX = Min(text_bounds.iTl.iX, 0);
1.176 + text_bounds.iBr.iX = Max(text_bounds.iBr.iX, advance);
1.177 + }
1.178 + else
1.179 + {
1.180 + text_bounds.iTl.iY = Min(text_bounds.iTl.iY, 0);
1.181 + text_bounds.iBr.iY = Max(text_bounds.iBr.iY, advance);
1.182 + }
1.183 + }
1.184 +
1.185 + // work out the text origin and new drawing position
1.186 + TPoint text_origin = aPosition;
1.187 + if (aDirection != CFont::EVertical)
1.188 + {
1.189 + const TInt leftSideBearing = Min(text_bounds.iTl.iX, 0);
1.190 + const TInt rightSideBearing = Max(text_bounds.iBr.iX, advance);
1.191 + switch (aAlignment)
1.192 + {
1.193 + // We are forbidding side-bearings to leak over the sides here,
1.194 + // but still keeping the start and end pen positions within bounds.
1.195 + case ELeft:
1.196 + text_origin.iX -= leftSideBearing;
1.197 + break;
1.198 + case ERight:
1.199 + text_origin.iX -= rightSideBearing;
1.200 + break;
1.201 + case ECenter:
1.202 + // Centre is the average of left and right
1.203 + text_origin.iX -= (leftSideBearing + rightSideBearing) >> 1;
1.204 + break;
1.205 + default:
1.206 + break;
1.207 + }
1.208 + }
1.209 + iLastPrintPosition = text_origin;
1.210 + if (aDirection == CFont::EHorizontal)
1.211 + iLastPrintPosition.iX += advance;
1.212 + else
1.213 + iLastPrintPosition.iY += advance;
1.214 + text_origin.iY += bitmap_font->iAlgStyle.iBaselineOffsetInPixels;
1.215 + text_bounds.Move(text_origin);
1.216 + text_origin += iOrigin;
1.217 +
1.218 + // determine clipping rectangle
1.219 + TRect clip_rect = aBox ? *aBox : text_bounds;
1.220 + AddRect(clip_rect);
1.221 + clip_rect.Move(iOrigin);
1.222 +
1.223 + if (UserClipRect(clip_rect))
1.224 + {
1.225 + if (iAutoUpdateJustification)
1.226 + UpdateJustification(aText,aParam);
1.227 + return; // nothing to do
1.228 + }
1.229 +
1.230 + SetupDevice();
1.231 + iDevice->DrawingBegin(&iBrushBitmap);
1.232 + CFbsRasterizer* brushRasterizer = PrepareRasterizerForExtendedBitmap(iBrushBitmap);
1.233 +
1.234 + // fill the box if necessary
1.235 + if (aBox)
1.236 + {
1.237 + TRect fill_box = *aBox;
1.238 + fill_box.Move(iOrigin);
1.239 + RectFill(fill_box);
1.240 + }
1.241 +
1.242 + // decide which drawing routine to call
1.243 + const TBool bold = bitmap_font->iAlgStyle.IsBold();
1.244 + const TBool italic = bitmap_font->iAlgStyle.IsItalic();
1.245 + const TBool multiw = bitmap_font->iAlgStyle.WidthFactor() > 1;
1.246 + const TBool multih = bitmap_font->iAlgStyle.HeightFactor() > 1;
1.247 +
1.248 + TOpenFontMetrics metrics;
1.249 + iFont.GetFontMetrics(metrics);
1.250 + const TInt maxwidth = metrics.MaxWidth();
1.251 + // extext will be TRUE, if font is bold/italic/underline/strikethrough/anti-aliased or it
1.252 + // has shadow/outline effects ON. Depending on these properties it will call the proper draw routine.
1.253 + TBool extext = FALSE;
1.254 + TBool normaltext = FALSE;
1.255 + const TBool anti_aliased = (bitmap_font->GlyphBitmapType() == EAntiAliasedGlyphBitmap);
1.256 + const TBool outlineAndShadow = (bitmap_font->GlyphBitmapType() == EFourColourBlendGlyphBitmap);
1.257 + if (anti_aliased || outlineAndShadow)
1.258 + {
1.259 + if ((outlineAndShadow) && !(iBrushStyle == ENullBrush || iBrushStyle == ESolidBrush))
1.260 + {
1.261 + //For future compatibility it is better if brush style of ENullBrush or ESolidBrush is used
1.262 + //when drawing outline and shadow fonts.
1.263 + BG_PANIC_ALWAYS(EBitgdiPanicInvalidBrushStyle);
1.264 + }
1.265 + extext = TRUE;
1.266 + }
1.267 + else if (maxwidth > 30 || text_bounds.Height() > 32 || multiw || multih)
1.268 + {
1.269 + }
1.270 + else if (iUnderline == EUnderlineOn || bold || italic || iStrikethrough == EStrikethroughOn ||
1.271 + iCharJustNum > 0 || iWordJustNum > 0)
1.272 + extext = TRUE;
1.273 + else
1.274 + normaltext = TRUE;
1.275 +
1.276 + const TInt charjustexcess = iCharJustExcess;
1.277 + const TInt charjustnum = iCharJustNum;
1.278 + const TInt wordjustexcess = iWordJustExcess;
1.279 + const TInt wordjustnum = iWordJustNum;
1.280 +
1.281 + // draw the text to all clip rectangles in turn
1.282 + int clip_rects = iDefaultRegionPtr->Count();
1.283 + for (int i = 0; i < clip_rects; i++)
1.284 + {
1.285 + iClipRect = (*iDefaultRegionPtr)[i];
1.286 + if (!iClipRect.Intersects(clip_rect))
1.287 + continue;
1.288 +
1.289 +#ifdef _DEBUG
1.290 + BG_ASSERT_DEBUG(iClipRect.iTl.iX >= deviceRect.iTl.iX, EBitgdiPanicOutOfBounds);
1.291 + BG_ASSERT_DEBUG(iClipRect.iTl.iY >= deviceRect.iTl.iY, EBitgdiPanicOutOfBounds);
1.292 + BG_ASSERT_DEBUG(iClipRect.iBr.iX <= deviceRect.iBr.iX, EBitgdiPanicOutOfBounds);
1.293 + BG_ASSERT_DEBUG(iClipRect.iBr.iY <= deviceRect.iBr.iY, EBitgdiPanicOutOfBounds);
1.294 +#endif
1.295 +
1.296 + iClipRect.Intersection(clip_rect);
1.297 +
1.298 + // Set up the parameter block for character positioning.
1.299 + CFont::TPositionParam param;
1.300 + param.iDirection = static_cast<TInt16>(aDirection);
1.301 + param.iText.Set(aText);
1.302 + TInt endDraw = aText.Length();
1.303 + if (aParam)
1.304 + {
1.305 + param.iPosInText = aParam->iStart;
1.306 + endDraw = Min(aText.Length(),aParam->iEnd);
1.307 + }
1.308 + else
1.309 + param.iPosInText = 0;
1.310 + param.iPen = text_origin;
1.311 +
1.312 + // Draw the text.
1.313 + if (normaltext)
1.314 + DoDrawText(param,endDraw);
1.315 + else if (extext)
1.316 + DoDrawTextEx(param,bitmap_font,endDraw,underlineStrikeoutOffset);
1.317 + else
1.318 + DoDrawTextLarge(param,bitmap_font,endDraw);
1.319 +
1.320 + /*
1.321 + Reset the justification parameters to their original values.
1.322 + These will be updated as required later in code.
1.323 + */
1.324 + iCharJustExcess = charjustexcess;
1.325 + iCharJustNum = charjustnum;
1.326 + iWordJustExcess = wordjustexcess;
1.327 + iWordJustNum = wordjustnum;
1.328 +
1.329 + drawDevice->UpdateRegion(iClipRect);
1.330 + }
1.331 +
1.332 + if (brushRasterizer)
1.333 + {
1.334 + brushRasterizer->EndBitmap(iBrushBitmap.SerialNumber());
1.335 + }
1.336 + iDevice->DrawingEnd(&iBrushBitmap);
1.337 + if (iAutoUpdateJustification)
1.338 + UpdateJustification(aText,aParam);
1.339 + }
1.340 +
1.341 +void CFbsBitGc::DoDrawText(CFont::TPositionParam& aParam, const TInt aEnd)
1.342 + {
1.343 + //const int n = aParam.iText.Length();
1.344 + RShapeInfo shapeInfo;
1.345 + while (aParam.iPosInText < /*n*/aEnd)
1.346 + {
1.347 + if (iFont.GetCharacterPosition2(aParam, shapeInfo))
1.348 + {
1.349 + const CFont::TPositionParam::TOutput* output = aParam.iOutput;
1.350 + for (int i = 0; i < aParam.iOutputGlyphs; i++, output++)
1.351 + DoDrawCharacter(output->iBounds.iTl,output->iBitmapSize,output->iBitmap);
1.352 + }
1.353 + }
1.354 + if (shapeInfo.IsOpen())
1.355 + shapeInfo.Close();
1.356 +
1.357 + }
1.358 +
1.359 +void CFbsBitGc::DoDrawCharacter(const TPoint& aTopLeft,
1.360 + const TSize& aDataSize,
1.361 + const TUint8* aData)
1.362 + {
1.363 + /*
1.364 + Divert if the character is larger than expected; the criterion
1.365 + for choosing this function is only a heuristic, because it's perfectly legal for
1.366 + a character's bitmap to be wider than its escapement.
1.367 +
1.368 + Use a dummy value (0) for semi-ascent because this character is not italic and so semi-ascent
1.369 + is irrelevant; it's used for pseudo-italic slanting.
1.370 + */
1.371 + TInt dataheight = aDataSize.iHeight;
1.372 + TInt datalength = aDataSize.iWidth;
1.373 + if (datalength > 30 || dataheight > 32)
1.374 + {
1.375 + DoDrawCharacterExLarge(aTopLeft,aDataSize,aData,FALSE,FALSE,0,1,1);
1.376 + return;
1.377 + }
1.378 +
1.379 + TInt bitindex=0;
1.380 + TInt16 repeatcount=0;
1.381 + TUint32 binarydata[32];
1.382 + TUint32* binarydataptr=binarydata;
1.383 + TUint32* binarydataptrlimit;
1.384 + for(TInt charline=0;charline<dataheight;charline+=repeatcount) // for lines in the character...
1.385 + {
1.386 + repeatcount=Load16(aData+(bitindex>>3));
1.387 + repeatcount>>=bitindex&7;
1.388 + TInt multilineflag=repeatcount&1;
1.389 + repeatcount>>=1;
1.390 + repeatcount&=0xf;
1.391 + bitindex+=5;
1.392 + binarydataptrlimit=binarydata+charline+repeatcount;
1.393 + if(multilineflag)
1.394 + {
1.395 + while(binarydataptr<binarydataptrlimit)
1.396 + {
1.397 + TInt chardataoffsetptr=TInt(aData)+(bitindex>>3);
1.398 + TUint32* chardataword=(TUint32*)(chardataoffsetptr&~3);
1.399 + TInt bitshift=bitindex&7;
1.400 + bitshift+=(chardataoffsetptr&3)<<3;
1.401 + *binarydataptr=(*chardataword++)>>bitshift;
1.402 + if(bitshift) *binarydataptr|=(*chardataword<<(32-bitshift));
1.403 + bitindex+=datalength;
1.404 + binarydataptr++;
1.405 + }
1.406 + }
1.407 + else
1.408 + {
1.409 + TInt chardataoffsetptr=TInt(aData)+(bitindex>>3);
1.410 + TUint32* chardataword=(TUint32*)(chardataoffsetptr&~3);
1.411 + TInt bitshift=bitindex&7;
1.412 + bitshift+=(chardataoffsetptr&3)<<3;
1.413 + TUint32 data=(*chardataword++)>>bitshift;
1.414 + if(bitshift) data|=(*chardataword<<(32-bitshift));
1.415 + while(binarydataptr<binarydataptrlimit)
1.416 + *binarydataptr++=data;
1.417 + bitindex+=datalength;
1.418 + }
1.419 + }
1.420 + TPoint topleft(aTopLeft);
1.421 + binarydataptr=ClipBinaryArray(binarydata,binarydata+dataheight,1,datalength,dataheight,topleft);
1.422 + if(datalength>0 && dataheight>0)
1.423 + iDevice->iDrawDevice->WriteBinary(topleft.iX,topleft.iY,binarydataptr,datalength,dataheight,iPenColor,iDrawMode);
1.424 + }
1.425 +
1.426 +/**
1.427 +@internalTechnology
1.428 +
1.429 +This function retrieves the baseline offset from the metrics of the text currently being drawn.
1.430 +This is used to alter the positioning of underline and strikethrough on a linked font
1.431 +
1.432 +@return The baseline correction associated with the currently used font.
1.433 +*/
1.434 +TInt CFbsBitGc::BaselineCorrection()
1.435 + {
1.436 + TOpenFontMetrics metrics;
1.437 + if (iFont.GetFontMetrics(metrics))
1.438 + return metrics.BaselineCorrection();
1.439 + else
1.440 + return 0;
1.441 + }
1.442 +
1.443 +void CFbsBitGc::DoDrawTextEx(CFont::TPositionParam& aParam,const CBitmapFont* font, const TInt aEnd, const TInt aUnderlineStrikethroughOffset)
1.444 + {
1.445 + const TInt charclipping = iClipRect.iBr.iX;
1.446 + TPoint start_pen = aParam.iPen;
1.447 + const TBool bold = font->iAlgStyle.IsBold();
1.448 + const TBool italic = font->iAlgStyle.IsItalic();
1.449 + const TGlyphBitmapType glyphBitmapTypeForFont = font->GlyphBitmapType();
1.450 + const TBool outlineShadowOrAntialiased = ((glyphBitmapTypeForFont == EAntiAliasedGlyphBitmap) ||
1.451 + (glyphBitmapTypeForFont == EFourColourBlendGlyphBitmap));
1.452 +
1.453 + TInt underline_top = 0, underline_bottom = 0;
1.454 + if (iUnderline == EUnderlineOn)
1.455 + {
1.456 + TInt err = GetUnderlineMetrics(underline_top,underline_bottom);
1.457 + underline_top+=aUnderlineStrikethroughOffset;
1.458 + underline_bottom+=aUnderlineStrikethroughOffset;
1.459 + BG_ASSERT_DEBUG(err == KErrNone, EBitgdiPanicInvalidArg);
1.460 + }
1.461 + TInt strike_top = 0, strike_bottom = 0;
1.462 + if (italic || iStrikethrough == EStrikethroughOn)
1.463 + {
1.464 + GetStrikethroughMetrics(strike_top,strike_bottom);
1.465 + strike_top+=aUnderlineStrikethroughOffset;
1.466 + strike_bottom+=aUnderlineStrikethroughOffset;
1.467 + }
1.468 +
1.469 + CFbsDrawDevice* drawDevice = iDevice->iDrawDevice;
1.470 + RShapeInfo shapeInfo;
1.471 + while (aParam.iPosInText < aEnd)
1.472 + {
1.473 + if (!iFont.GetCharacterPosition2(aParam, shapeInfo))
1.474 + continue;
1.475 + TInt adjustment = 0;
1.476 + if(iCharJustExcess && iCharJustNum > 0) // character clipping/justification
1.477 + {
1.478 + adjustment = CGraphicsContext::JustificationInPixels(iCharJustExcess,iCharJustNum);
1.479 + if(adjustment < 0)
1.480 + iClipRect.iBr.iX = Min(aParam.iPen.iX + adjustment,iClipRect.iBr.iX);
1.481 + }
1.482 +
1.483 + const CFont::TPositionParam::TOutput* output = aParam.iOutput;
1.484 + int semi_ascent = start_pen.iY + strike_top;
1.485 +
1.486 + for (int i = 0; i < aParam.iOutputGlyphs; i++, output++)
1.487 + {
1.488 + //get the character metrics for the glyph type
1.489 + TOpenFontCharMetrics characterParams;
1.490 + const TUint8* bitmap;
1.491 + TSize size;
1.492 + //note may now be using a glyph code, and not a character
1.493 + iFont.GetCharacterData(aParam.iOutput[i].iCode,characterParams,bitmap,size);
1.494 + TGlyphBitmapType glyphType = characterParams.GlyphType();
1.495 +
1.496 + switch (glyphType)
1.497 + {
1.498 + case EAntiAliasedGlyphBitmap:
1.499 + case EFourColourBlendGlyphBitmap:
1.500 + DoDrawCharacterAntiAliased(output->iBounds.iTl,output->iBitmapSize,output->iBitmap,glyphType);
1.501 + break;
1.502 +
1.503 + case EDefaultGlyphBitmap:
1.504 + case EMonochromeGlyphBitmap:
1.505 + DoDrawCharacterEx(output->iBounds.iTl,output->iBitmapSize,output->iBitmap,bold,italic,semi_ascent);
1.506 + break;
1.507 +
1.508 + default:
1.509 + //if the outline or shadow is not specified for the character, then use the font setting
1.510 + if (outlineShadowOrAntialiased)
1.511 + {
1.512 + DoDrawCharacterAntiAliased(output->iBounds.iTl,output->iBitmapSize,output->iBitmap,glyphBitmapTypeForFont);
1.513 + }
1.514 + else
1.515 + {
1.516 + DoDrawCharacterEx(output->iBounds.iTl,output->iBitmapSize,output->iBitmap,bold,italic,semi_ascent);
1.517 + }
1.518 + break;
1.519 + }
1.520 + }
1.521 +
1.522 + iClipRect.iBr.iX = charclipping;
1.523 + if (adjustment)
1.524 + aParam.iPen.iX += adjustment;
1.525 + if (iWordJustExcess > 0 && iWordJustNum > 0 && aParam.iOutput[0].iCode == 0x0020) // word justification
1.526 + {
1.527 + adjustment = CGraphicsContext::JustificationInPixels(iWordJustExcess,iWordJustNum);
1.528 + aParam.iPen.iX += adjustment;
1.529 + }
1.530 + }
1.531 + if (shapeInfo.IsOpen())
1.532 + shapeInfo.Close();
1.533 +
1.534 + if (iUnderline == EUnderlineOn)
1.535 + {
1.536 + TRect ul(start_pen.iX,start_pen.iY + underline_top,aParam.iPen.iX,start_pen.iY + underline_bottom);
1.537 + if(ul.Intersects(iClipRect)) // checks for empty aRect as well
1.538 + {
1.539 + ul.Intersection(iClipRect);
1.540 + drawDevice->WriteRgbMulti(ul.iTl.iX,ul.iTl.iY,ul.iBr.iX-ul.iTl.iX,ul.iBr.iY-ul.iTl.iY,iPenColor,iDrawMode);
1.541 + }
1.542 + }
1.543 +
1.544 + if (iStrikethrough == EStrikethroughOn)
1.545 + {
1.546 + TRect st(start_pen.iX,start_pen.iY + strike_top,aParam.iPen.iX,start_pen.iY + strike_bottom);
1.547 + if(st.Intersects(iClipRect)) // checks for empty aRect as well
1.548 + {
1.549 + st.Intersection(iClipRect);
1.550 + drawDevice->WriteRgbMulti(st.iTl.iX,st.iTl.iY,st.iBr.iX-st.iTl.iX,st.iBr.iY-st.iTl.iY,iPenColor,iDrawMode);
1.551 + }
1.552 + }
1.553 + }
1.554 +
1.555 +void CFbsBitGc::DoDrawCharacterEx(const TPoint& aTopLeft,
1.556 + const TSize& aDataSize,
1.557 + const TUint8* aData,
1.558 + TBool aBold,TBool aItalic,TInt aSemiAscent)
1.559 + {
1.560 + /*
1.561 + Divert if the character is larger than expected; the criterion
1.562 + for choosing this function is only a heuristic, because it's perfectly legal for
1.563 + a character's bitmap to be wider than its escapement.
1.564 + */
1.565 + TInt datalength = aDataSize.iWidth;
1.566 + TInt dataheight = aDataSize.iHeight;
1.567 + if (datalength > 30 || dataheight > 32)
1.568 + {
1.569 + DoDrawCharacterExLarge(aTopLeft,aDataSize,aData,aBold,aItalic,aSemiAscent,1,1);
1.570 + return;
1.571 + }
1.572 +
1.573 + TInt bitindex=0;
1.574 + TInt16 repeatcount=0;
1.575 + TUint32 binarydata[32];
1.576 + TUint32* binarydataptr=binarydata;
1.577 + TUint32* binarydataptrlimit;
1.578 + for(TInt charline=0;charline<dataheight;charline+=repeatcount) // for lines in the character...
1.579 + {
1.580 + repeatcount=Load16(aData+(bitindex>>3));
1.581 + repeatcount>>=bitindex&7;
1.582 + TInt multilineflag=repeatcount&1;
1.583 + repeatcount>>=1;
1.584 + repeatcount&=0xf;
1.585 + bitindex+=5;
1.586 + binarydataptrlimit=binarydata+charline+repeatcount;
1.587 + if(multilineflag)
1.588 + {
1.589 + while(binarydataptr<binarydataptrlimit)
1.590 + {
1.591 + CopyCharWord(binarydataptr,aData+(bitindex>>3),bitindex&7);
1.592 + bitindex+=datalength;
1.593 + binarydataptr++;
1.594 + }
1.595 + }
1.596 + else
1.597 + {
1.598 + TUint32 data=0;
1.599 + CopyCharWord(&data,aData+(bitindex>>3),bitindex&7);
1.600 + while(binarydataptr<binarydataptrlimit)
1.601 + *binarydataptr++=data;
1.602 + bitindex+=datalength;
1.603 + }
1.604 + }
1.605 + binarydataptr=binarydata;
1.606 + binarydataptrlimit=binarydata+dataheight;
1.607 + if(aBold)
1.608 + {
1.609 + TInt sparemask=(0xffffffff>>(32-datalength));
1.610 + while(binarydataptr<binarydataptrlimit)
1.611 + {
1.612 + *binarydataptr&=sparemask;
1.613 + *binarydataptr|=(*binarydataptr<<1);
1.614 + ++binarydataptr;
1.615 + }
1.616 + binarydataptr=binarydata;
1.617 + datalength++;
1.618 + }
1.619 + if(aItalic)
1.620 + {
1.621 + TInt skewlevel=aSemiAscent-aTopLeft.iY;
1.622 + TUint32 sparemask=(0xffffffff>>(32-datalength));
1.623 + binarydataptrlimit=binarydata+skewlevel;
1.624 + while(binarydataptr<binarydataptrlimit)
1.625 + *binarydataptr++<<=1;
1.626 + binarydataptrlimit=binarydata+dataheight;
1.627 + while(binarydataptr<binarydataptrlimit)
1.628 + *binarydataptr++&=sparemask;
1.629 + binarydataptr=binarydata;
1.630 + datalength++;
1.631 + }
1.632 + TPoint topleft(aTopLeft);
1.633 + binarydataptr=ClipBinaryArray(binarydata,binarydata+dataheight,1,datalength,dataheight,topleft);
1.634 + if(datalength>0 && dataheight>0)
1.635 + iDevice->iDrawDevice->WriteBinary(topleft.iX,topleft.iY,binarydataptr,datalength,dataheight,iPenColor,iDrawMode);
1.636 + }
1.637 +
1.638 +/**
1.639 +@internalTechnology
1.640 +
1.641 +This function draws an anti-aliased character.
1.642 +
1.643 +@param aTopLeft The position to output the character
1.644 +@param aDataSize The size of the bitmap
1.645 +@param aData the bitmap for outputt in their TOpenFontCharMetrics
1.646 +@param aGlyphType the glyph type for the character
1.647 +*/
1.648 +void CFbsBitGc::DoDrawCharacterAntiAliased(const TPoint& aTopLeft,
1.649 + const TSize& aDataSize,
1.650 + const TUint8* aData,
1.651 + const TGlyphBitmapType aGlyphType)
1.652 + {
1.653 + const int top_row = Max(0,iClipRect.iTl.iY - aTopLeft.iY);
1.654 + const int bottom_row = Min(aDataSize.iHeight,iClipRect.iBr.iY - aTopLeft.iY);
1.655 + const int left_col = Max(0,iClipRect.iTl.iX - aTopLeft.iX);
1.656 + const int right_col = Min(aDataSize.iWidth,iClipRect.iBr.iX - aTopLeft.iX);
1.657 + const TUint8* p = aData + top_row * aDataSize.iWidth + left_col;
1.658 + const int x = aTopLeft.iX + left_col;
1.659 + int y = aTopLeft.iY + top_row;
1.660 + const int cols = right_col - left_col;
1.661 + const TUint32 penColor = iPenColor.Internal();
1.662 + const TUint32 shadowColor = iFbsBitGcExtraData->ShadowColor().Internal();
1.663 + const TUint32 brushColor = iBrushColor.Internal();
1.664 +
1.665 + if (EFourColourBlendGlyphBitmap == aGlyphType)
1.666 + {
1.667 + MOutlineAndShadowBlend* outlineAndShadow = NULL;
1.668 + const TInt err = iDevice->iDrawDevice->GetInterface(KOutlineAndShadowInterfaceID, reinterpret_cast <TAny*&> (outlineAndShadow));
1.669 + if(err == KErrNone)
1.670 + {
1.671 + //There is a support for the interface with KOutlineAndShadowInterface id.
1.672 + for (int row = top_row; row < bottom_row; row++, p += aDataSize.iWidth, y++)
1.673 + outlineAndShadow->WriteRgbOutlineAndShadow(x, y, cols, penColor, shadowColor, brushColor, p);
1.674 + }
1.675 + else
1.676 + {
1.677 + // Assert if MOutlineAndShadowBlend interface is not implemented
1.678 + BG_ASSERT_DEBUG(outlineAndShadow, EBitgdiPanicInvalidInterfaceHandle);
1.679 + }
1.680 + }
1.681 + else
1.682 + {
1.683 + for (int row = top_row; row < bottom_row; row++, p += aDataSize.iWidth, y++)
1.684 + iDevice->iDrawDevice->WriteRgbAlphaMulti(x,y,cols,iPenColor,p);
1.685 + }
1.686 + }
1.687 +
1.688 +void CFbsBitGc::DoDrawTextLarge(CFont::TPositionParam& aParam,const CBitmapFont* font,const TInt aEnd)
1.689 + {
1.690 + const TInt charclipping = iClipRect.iBr.iX;
1.691 + TPoint start_pen = aParam.iPen;
1.692 + const TInt strikeheight = start_pen.iY - (font->CBitmapFont::DoAscentInPixels() * 5/12) - 1;
1.693 + const TBool bold = font->iAlgStyle.IsBold();
1.694 + const TBool italic = font->iAlgStyle.IsItalic();
1.695 + const TInt widthfactor=font->iAlgStyle.WidthFactor();
1.696 + const TInt heightfactor=font->iAlgStyle.HeightFactor();
1.697 +
1.698 + CFbsDrawDevice* drawDevice = iDevice->iDrawDevice;
1.699 +
1.700 + RShapeInfo shapeInfo;
1.701 + while (aParam.iPosInText < aEnd)
1.702 + {
1.703 + if (!iFont.GetCharacterPosition2(aParam, shapeInfo))
1.704 + continue;
1.705 + TInt adjustment = 0;
1.706 + if(iCharJustExcess && iCharJustNum > 0) // character clipping/justification
1.707 + {
1.708 + adjustment = CGraphicsContext::JustificationInPixels(iCharJustExcess,iCharJustNum);
1.709 + if(adjustment < 0)
1.710 + iClipRect.iBr.iX = Min(aParam.iPen.iX + adjustment,iClipRect.iBr.iX);
1.711 + }
1.712 +
1.713 + const CFont::TPositionParam::TOutput* output = aParam.iOutput;
1.714 + for (int i = 0; i < aParam.iOutputGlyphs; i++, output++)
1.715 + DoDrawCharacterLarge(output->iBounds.iTl,output->iBitmapSize,output->iBitmap,bold,italic,strikeheight,
1.716 + widthfactor,heightfactor);
1.717 +
1.718 + iClipRect.iBr.iX = charclipping;
1.719 + if (adjustment)
1.720 + aParam.iPen.iX += adjustment;
1.721 + if (iWordJustExcess > 0 && iWordJustNum > 0 && aParam.iOutput[0].iCode == 0x0020) // word justification
1.722 + {
1.723 + adjustment = CGraphicsContext::JustificationInPixels(iWordJustExcess,iWordJustNum);
1.724 + aParam.iPen.iX += adjustment;
1.725 + }
1.726 + }
1.727 + if (shapeInfo.IsOpen())
1.728 + shapeInfo.Close();
1.729 + const TInt ulwidth = Max(font->CBitmapFont::DoHeightInPixels() / 10, 1);
1.730 + if (iUnderline == EUnderlineOn)
1.731 + {
1.732 + TInt ulstart = start_pen.iY + 1 + ulwidth / 2;
1.733 + TRect ul(start_pen.iX,ulstart,aParam.iPen.iX,ulstart + ulwidth);
1.734 + if(ul.Intersects(iClipRect)) // checks for empty aRect as well
1.735 + {
1.736 + ul.Intersection(iClipRect);
1.737 + drawDevice->WriteRgbMulti(ul.iTl.iX,ul.iTl.iY,ul.iBr.iX-ul.iTl.iX,ul.iBr.iY-ul.iTl.iY,iPenColor,iDrawMode);
1.738 + }
1.739 + }
1.740 +
1.741 + if (iStrikethrough == EStrikethroughOn)
1.742 + {
1.743 + TRect st(start_pen.iX,strikeheight,aParam.iPen.iX,strikeheight + ulwidth);
1.744 + if(st.Intersects(iClipRect)) // checks for empty aRect as well
1.745 + {
1.746 + st.Intersection(iClipRect);
1.747 + drawDevice->WriteRgbMulti(st.iTl.iX,st.iTl.iY,st.iBr.iX-st.iTl.iX,st.iBr.iY-st.iTl.iY,iPenColor,iDrawMode);
1.748 + }
1.749 + }
1.750 + }
1.751 +
1.752 +void CFbsBitGc::DoDrawCharacterLarge(const TPoint& aTopLeft,const TSize& aDataSize,const TUint8* aData,
1.753 + TBool aBold,TBool aItalic,TInt aSemiAscent,TInt aWidthFactor,TInt aHeightFactor)
1.754 + {
1.755 + TInt datalength = aDataSize.iWidth;
1.756 + TInt dataheight = aDataSize.iHeight;
1.757 +
1.758 + if (aWidthFactor > 2 || aHeightFactor > 2)
1.759 + {
1.760 + DoDrawCharacterMultiplied(aTopLeft,aDataSize,aData,aBold,aItalic,aSemiAscent,aWidthFactor,aHeightFactor);
1.761 + return;
1.762 + }
1.763 +
1.764 + if (datalength > 30 || dataheight > 32 || (aWidthFactor == 2 && datalength > 14))
1.765 + {
1.766 + DoDrawCharacterExLarge(aTopLeft,aDataSize,aData,aBold,aItalic,aSemiAscent,aWidthFactor,aHeightFactor);
1.767 + return;
1.768 + }
1.769 +
1.770 + TInt italicheight=aSemiAscent-aTopLeft.iY;
1.771 + if(aHeightFactor==2) italicheight>>=1;
1.772 + TInt bitindex=0;
1.773 + TInt16 repeatcount=0;
1.774 + TUint32 binarydata[64];
1.775 + TUint32* binarydataptr=binarydata;
1.776 + TUint32* binarydataptrlimit;
1.777 +
1.778 + for(TInt charline=0;charline<dataheight;charline+=repeatcount) // for lines in the character...
1.779 + {
1.780 + repeatcount=Load16(aData+(bitindex>>3));
1.781 + repeatcount>>=bitindex&7;
1.782 + TInt multilineflag=repeatcount&1;
1.783 + repeatcount>>=1;
1.784 + repeatcount&=0xf;
1.785 + bitindex+=5;
1.786 + binarydataptrlimit=binarydata+charline+repeatcount;
1.787 + if(multilineflag)
1.788 + {
1.789 + while(binarydataptr<binarydataptrlimit)
1.790 + {
1.791 + CopyCharWord(binarydataptr,aData+(bitindex>>3),bitindex&7);
1.792 + bitindex+=datalength;
1.793 + binarydataptr++;
1.794 + }
1.795 + }
1.796 + else
1.797 + {
1.798 + TUint32 data=0;
1.799 + CopyCharWord(&data,aData+(bitindex>>3),bitindex&7);
1.800 + while(binarydataptr<binarydataptrlimit)
1.801 + *binarydataptr++=data;
1.802 + bitindex+=datalength;
1.803 + }
1.804 + }
1.805 + binarydataptr=binarydata;
1.806 + binarydataptrlimit=binarydata+dataheight;
1.807 + if(aBold)
1.808 + {
1.809 + TInt sparemask=(0xffffffff>>(32-datalength));
1.810 + while(binarydataptr<binarydataptrlimit)
1.811 + {
1.812 + *binarydataptr&=sparemask;
1.813 + *binarydataptr|=(*binarydataptr<<1);
1.814 + ++binarydataptr;
1.815 + }
1.816 + binarydataptr=binarydata;
1.817 + datalength++;
1.818 + }
1.819 + if(aItalic)
1.820 + {
1.821 + TUint32 sparemask=(0xffffffff>>(32-datalength));
1.822 + binarydataptrlimit=Min(binarydataptrlimit,binarydata+italicheight);
1.823 + while(binarydataptr<binarydataptrlimit)
1.824 + {
1.825 + *binarydataptr<<=1;
1.826 + *binarydataptr++&=0xfffffffe;
1.827 + }
1.828 + binarydataptrlimit=binarydata+dataheight;
1.829 + while(binarydataptr<binarydataptrlimit)
1.830 + *binarydataptr++&=sparemask;
1.831 + binarydataptr=binarydata;
1.832 + datalength++;
1.833 + }
1.834 + if(aWidthFactor==2)
1.835 + {
1.836 + BG_ASSERT_DEBUG(datalength<=16,EBitgdiPanicCharacterTooBig);
1.837 + while(binarydataptr<binarydataptrlimit)
1.838 + {
1.839 + TUint32 singlemask=0x8000;
1.840 + TUint32 doublemask=0xc0000000;
1.841 + TUint32 newdata=0;
1.842 + while(singlemask)
1.843 + {
1.844 + if(*binarydataptr&singlemask)
1.845 + newdata|=doublemask;
1.846 + singlemask>>=1;
1.847 + doublemask>>=2;
1.848 + }
1.849 + *binarydataptr++=newdata;
1.850 + }
1.851 + datalength<<=1;
1.852 + binarydataptr=binarydata;
1.853 + }
1.854 + if(aHeightFactor==2)
1.855 + {
1.856 + binarydataptr=binarydata+dataheight-1;
1.857 + TUint32* tempptr=binarydataptr+dataheight;
1.858 + while(binarydataptr>=binarydata)
1.859 + {
1.860 + *tempptr--=*binarydataptr;
1.861 + *tempptr--=*binarydataptr--;
1.862 + }
1.863 + dataheight<<=1;
1.864 + binarydataptr=binarydata;
1.865 + }
1.866 + TPoint startpos=aTopLeft;
1.867 + binarydataptr=ClipBinaryArray(binarydata,binarydata+dataheight,1,datalength,dataheight,startpos);
1.868 + if(datalength>0 && dataheight>0)
1.869 + iDevice->iDrawDevice->WriteBinary(startpos.iX,startpos.iY,binarydataptr,datalength,dataheight,iPenColor,iDrawMode);
1.870 + }
1.871 +
1.872 +void CFbsBitGc::DoDrawCharacterExLarge(const TPoint& aTopLeft,const TSize& aDataSize,const TUint8* aData,
1.873 + TBool aBold,TBool aItalic,TInt aSemiAscent,TInt aWidthFactor,TInt aHeightFactor)
1.874 + {
1.875 + CFbsDrawDevice* drawDevice = iDevice->iDrawDevice;
1.876 + TPoint printpos(aTopLeft);
1.877 + const TInt datalength = aDataSize.iWidth;
1.878 + const TInt dataheight = aDataSize.iHeight;
1.879 + TInt bitindex=0;
1.880 + TInt16 repeatcount=0;
1.881 + TUint32* slbuffer=drawDevice->ScanLineBuffer();
1.882 + const TInt slwords=(drawDevice->ScanLineBytes())<<3;
1.883 + if(aItalic && aTopLeft.iY<aSemiAscent)
1.884 + printpos.iX++;
1.885 + for(TInt charline=0;charline<dataheight;charline+=repeatcount) // for lines in the character...
1.886 + {
1.887 + repeatcount=Load16(aData+(bitindex>>3));
1.888 + repeatcount>>=bitindex&7;
1.889 + const TInt multilineflag=repeatcount&1;
1.890 + repeatcount>>=1;
1.891 + repeatcount&=0xf;
1.892 + bitindex+=5;
1.893 + if(multilineflag)
1.894 + {
1.895 + for(TInt currentline=0;currentline<repeatcount;currentline++)
1.896 + {
1.897 + CopyCharLine(slbuffer,slwords,aData+(bitindex>>3),bitindex&7,datalength);
1.898 + OutputCharLineMultiplied(printpos,slbuffer,datalength,1,aBold,aWidthFactor,aHeightFactor);
1.899 + bitindex+=datalength;
1.900 + printpos.iY++;
1.901 + if(printpos.iY==aSemiAscent && aItalic) printpos.iX--;
1.902 + if(aHeightFactor==2)
1.903 + {
1.904 + printpos.iY++;
1.905 + if(printpos.iY==aSemiAscent && aItalic) printpos.iX--;
1.906 + }
1.907 + }
1.908 + }
1.909 + else
1.910 + {
1.911 + if(aItalic)
1.912 + {
1.913 + for(TInt currentline=0;currentline<repeatcount;currentline++)
1.914 + {
1.915 + CopyCharLine(slbuffer,slwords,aData+(bitindex>>3),bitindex&7,datalength);
1.916 + OutputCharLineMultiplied(printpos,slbuffer,datalength,1,aBold,aWidthFactor,aHeightFactor);
1.917 + printpos.iY++;
1.918 + if(printpos.iY==aSemiAscent && aItalic) printpos.iX--;
1.919 + if(aHeightFactor==2)
1.920 + {
1.921 + printpos.iY++;
1.922 + if(printpos.iY==aSemiAscent && aItalic) printpos.iX--;
1.923 + }
1.924 + }
1.925 + }
1.926 + else
1.927 + {
1.928 + CopyCharLine(slbuffer,slwords,aData+(bitindex>>3),bitindex&7,datalength);
1.929 + OutputCharLineMultiplied(printpos,slbuffer,datalength,repeatcount,aBold,aWidthFactor,aHeightFactor);
1.930 + printpos.iY+=repeatcount;
1.931 + if(aHeightFactor==2) printpos.iY+=repeatcount;
1.932 + }
1.933 + bitindex+=datalength;
1.934 + }
1.935 + }
1.936 + }
1.937 +
1.938 +void CFbsBitGc::DoDrawCharacterMultiplied(const TPoint& aTopLeft,const TSize& aDataSize,const TUint8* aData,
1.939 + TBool aBold,TBool aItalic,TInt aSemiAscent,TInt aWidthFactor,TInt aHeightFactor)
1.940 + {
1.941 + CFbsDrawDevice* drawDevice = iDevice->iDrawDevice;
1.942 + TPoint printpos(aTopLeft);
1.943 + const TInt datalength = aDataSize.iWidth;
1.944 + const TInt dataheight = aDataSize.iHeight;
1.945 + TInt bitindex=0;
1.946 + TInt16 repeatcount=0;
1.947 + TUint32* slbuffer=drawDevice->ScanLineBuffer();
1.948 + const TInt slwords=(drawDevice->ScanLineBytes())<<3;
1.949 + if(aItalic && aTopLeft.iY<aSemiAscent)
1.950 + printpos.iX++;
1.951 + for(TInt charline=0;charline<dataheight;charline+=repeatcount) // for lines in the character...
1.952 + {
1.953 + repeatcount=Load16(aData+(bitindex>>3));
1.954 + repeatcount>>=bitindex&7;
1.955 + const TInt multilineflag=repeatcount&1;
1.956 + repeatcount>>=1;
1.957 + repeatcount&=0xf;
1.958 + bitindex+=5;
1.959 + if(multilineflag)
1.960 + {
1.961 + for(TInt currentline=0;currentline<repeatcount;currentline++)
1.962 + {
1.963 + CopyCharLine(slbuffer,slwords,aData+(bitindex>>3),bitindex&7,datalength);
1.964 + OutputCharLineMultiplied(printpos,slbuffer,datalength,1,aBold,aWidthFactor,aHeightFactor);
1.965 + bitindex+=datalength;
1.966 + TBool aboveitalicjump=EFalse;
1.967 + if(aItalic && printpos.iY<aSemiAscent) aboveitalicjump=ETrue;
1.968 + printpos.iY+=aHeightFactor;
1.969 + if(aboveitalicjump && printpos.iY>=aSemiAscent) printpos.iX-=aWidthFactor;
1.970 + }
1.971 + }
1.972 + else
1.973 + {
1.974 + if(aItalic)
1.975 + {
1.976 + for(TInt currentline=0;currentline<repeatcount;currentline++)
1.977 + {
1.978 + CopyCharLine(slbuffer,slwords,aData+(bitindex>>3),bitindex&7,datalength);
1.979 + OutputCharLineMultiplied(printpos,slbuffer,datalength,1,aBold,aWidthFactor,aHeightFactor);
1.980 + TBool aboveitalicjump=EFalse;
1.981 + if(printpos.iY<aSemiAscent) aboveitalicjump=ETrue;
1.982 + printpos.iY+=aHeightFactor;
1.983 + if(aboveitalicjump && printpos.iY>=aSemiAscent) printpos.iX-=aWidthFactor;
1.984 + }
1.985 + }
1.986 + else
1.987 + {
1.988 + CopyCharLine(slbuffer,slwords,aData+(bitindex>>3),bitindex&7,datalength);
1.989 + OutputCharLineMultiplied(printpos,slbuffer,datalength,repeatcount,aBold,aWidthFactor,aHeightFactor);
1.990 + printpos.iY+=repeatcount*aHeightFactor;
1.991 + }
1.992 + bitindex+=datalength;
1.993 + }
1.994 + }
1.995 + }
1.996 +
1.997 +void CFbsBitGc::OutputCharLineMultiplied(TPoint aPrintPos,TUint32* aBuffer,TInt aDataLength,TInt aNum,TBool aBold,TInt aWidthFactor,TInt aHeightFactor)
1.998 + {
1.999 + if(aDataLength<=0) return;
1.1000 + TInt bufferwords=(aDataLength+31)>>5;
1.1001 + TUint32* bufferlimit=aBuffer+bufferwords;
1.1002 + if(aBold)
1.1003 + {
1.1004 + TInt sparemask=(0xffffffff>>(32-(aDataLength&0x1f)));
1.1005 + if((aDataLength&0x1f)==0) sparemask=0xffffffff;
1.1006 + *(bufferlimit-1)&=sparemask;
1.1007 + TUint32* bufferptr=aBuffer;
1.1008 + TUint32 extrabit=0;
1.1009 + while(bufferptr<bufferlimit)
1.1010 + {
1.1011 + extrabit=*bufferptr>>31;
1.1012 + *bufferptr|=(*bufferptr<<1);
1.1013 + ++bufferptr;
1.1014 + if(bufferptr<bufferlimit)
1.1015 + *bufferptr|=extrabit;
1.1016 + }
1.1017 + aDataLength++;
1.1018 + if((aDataLength&0x1f)==1)
1.1019 + {
1.1020 + bufferwords++;
1.1021 + *bufferlimit=extrabit;
1.1022 + bufferlimit++;
1.1023 + }
1.1024 + }
1.1025 + if(aWidthFactor>1)
1.1026 + {
1.1027 + BitMultiply(aBuffer,aDataLength,aWidthFactor);
1.1028 + aDataLength*=aWidthFactor;
1.1029 + bufferwords=(aDataLength+31)>>5;
1.1030 + bufferlimit=aBuffer+bufferwords;
1.1031 + }
1.1032 + if(aPrintPos.iX<iClipRect.iTl.iX)
1.1033 + {
1.1034 + TInt pixelexcess=iClipRect.iTl.iX-aPrintPos.iX;
1.1035 + while(pixelexcess>=32)
1.1036 + {
1.1037 + aBuffer++;
1.1038 + bufferwords--;
1.1039 + aDataLength-=32;
1.1040 + pixelexcess-=32;
1.1041 + }
1.1042 + if(aDataLength<=0) return;
1.1043 + if(pixelexcess>0)
1.1044 + {
1.1045 + TInt shiftup=32-pixelexcess;
1.1046 + TUint32* bufferptr=aBuffer;
1.1047 + while(bufferptr<bufferlimit)
1.1048 + {
1.1049 + *bufferptr>>=pixelexcess;
1.1050 + if(bufferptr<bufferlimit-1)
1.1051 + *bufferptr|=(*(bufferptr+1)<<shiftup);
1.1052 + bufferptr++;
1.1053 + }
1.1054 + aDataLength-=pixelexcess;
1.1055 + if(aDataLength<=0) return;
1.1056 + }
1.1057 + aPrintPos.iX=iClipRect.iTl.iX;
1.1058 + }
1.1059 + if(aPrintPos.iX+aDataLength>iClipRect.iBr.iX)
1.1060 + {
1.1061 + TInt pixelexcess=aPrintPos.iX+aDataLength-iClipRect.iBr.iX;
1.1062 + aDataLength-=pixelexcess;
1.1063 + if(aDataLength<=0) return;
1.1064 + }
1.1065 + aNum*=aHeightFactor;
1.1066 + while(aNum>0)
1.1067 + {
1.1068 + if(aPrintPos.iY>=iClipRect.iTl.iY && aPrintPos.iY<iClipRect.iBr.iY)
1.1069 + iDevice->iDrawDevice->WriteBinaryLine(aPrintPos.iX,aPrintPos.iY,aBuffer,aDataLength,iPenColor,iDrawMode);
1.1070 + aPrintPos.iY++;
1.1071 + aNum--;
1.1072 + }
1.1073 + }
1.1074 +
1.1075 +void CFbsBitGc::CopyCharWord(TUint32* aBinaryDataPtr,const TUint8* aData,TInt aBitShift)
1.1076 + {
1.1077 + const TUint32* dataword=(TUint32*)(TInt(aData)&~3);
1.1078 + aBitShift+=(TInt(aData)-TInt(dataword))<<3;
1.1079 + *aBinaryDataPtr=*dataword++;
1.1080 + if(aBitShift<32) *aBinaryDataPtr>>=aBitShift;
1.1081 + if(aBitShift) *aBinaryDataPtr|=(*dataword<<(32-aBitShift));
1.1082 + }
1.1083 +
1.1084 +void CFbsBitGc::CopyCharLine(TUint32* aBinaryDataPtr,TInt aBufferWords,const TUint8* aData,TInt aBitShift,TInt aCharWidth)
1.1085 + {
1.1086 + aBitShift&=7;
1.1087 + TInt wordstocopy=(aCharWidth+31)>>5;
1.1088 + if(wordstocopy>aBufferWords) wordstocopy=aBufferWords;
1.1089 + TUint32* ptrlimit=aBinaryDataPtr+wordstocopy;
1.1090 + TUint32* dataword=(TUint32*)(TInt(aData)&~3);
1.1091 + aBitShift+=(TInt(aData)-TInt(dataword))<<3;
1.1092 + while(aBinaryDataPtr<ptrlimit)
1.1093 + {
1.1094 + *aBinaryDataPtr=*dataword++;
1.1095 + *aBinaryDataPtr>>=aBitShift;
1.1096 + if(aBitShift) *aBinaryDataPtr|=(*dataword<<(32-aBitShift));
1.1097 + aBinaryDataPtr++;
1.1098 + }
1.1099 + }
1.1100 +
1.1101 +TUint32* CFbsBitGc::ClipBinaryArray(TUint32* aArray,TUint32* aArrayLimit,TInt aArrayWordWd,TInt& aDataWd,TInt& aDataHt,TPoint& aPos)
1.1102 + {
1.1103 + TUint32* arrayptr=aArray;
1.1104 + TInt clipdiff=iClipRect.iTl.iX-aPos.iX;
1.1105 + if(aArrayWordWd==1)
1.1106 + {
1.1107 + if(clipdiff>0)
1.1108 + {
1.1109 + while(arrayptr<aArrayLimit)
1.1110 + *arrayptr++>>=clipdiff;
1.1111 + aDataWd-=clipdiff;
1.1112 + aPos.iX=iClipRect.iTl.iX;
1.1113 + arrayptr=aArray;
1.1114 + }
1.1115 + if(aPos.iX+aDataWd>iClipRect.iBr.iX && aDataWd>0)
1.1116 + aDataWd=iClipRect.iBr.iX-aPos.iX;
1.1117 + clipdiff=iClipRect.iTl.iY-aPos.iY;
1.1118 + if(clipdiff>0)
1.1119 + {
1.1120 + aDataHt-=clipdiff;
1.1121 + arrayptr+=clipdiff;
1.1122 + aPos.iY=iClipRect.iTl.iY;
1.1123 + }
1.1124 + if(aPos.iY+aDataHt>iClipRect.iBr.iY && aDataHt>0)
1.1125 + aDataHt=iClipRect.iBr.iY-aPos.iY;
1.1126 + }
1.1127 + return(arrayptr);
1.1128 + }
1.1129 +
1.1130 +void CFbsBitGc::BitMultiply(TUint32* aBinaryDataPtr,TInt aBitLength,TInt aFactor)
1.1131 + {
1.1132 + TInt bitpos=aBitLength-1;
1.1133 + TUint32* wordpos=aBinaryDataPtr+(bitpos>>5);
1.1134 + TInt bitoffset=bitpos&0x1f;
1.1135 + TInt multbitpos=(aBitLength*aFactor)-1;
1.1136 + TUint32* multwordpos=aBinaryDataPtr+(multbitpos>>5);
1.1137 + TInt multbitoffset=multbitpos&0x1f;
1.1138 + while(bitpos>=0)
1.1139 + {
1.1140 + TUint32 bit=((*wordpos)>>bitoffset)&1;
1.1141 + TInt next=multbitpos-aFactor;
1.1142 + while(multbitpos>next)
1.1143 + {
1.1144 + if(bit) *multwordpos|=(1<<multbitoffset);
1.1145 + else *multwordpos&=~(1<<multbitoffset);
1.1146 + multbitpos--;
1.1147 + multbitoffset--;
1.1148 + if(multbitoffset<0)
1.1149 + {
1.1150 + multbitoffset=31;
1.1151 + multwordpos--;
1.1152 + }
1.1153 + }
1.1154 + bitpos--;
1.1155 + bitoffset--;
1.1156 + if(bitoffset<0)
1.1157 + {
1.1158 + bitoffset=31;
1.1159 + wordpos--;
1.1160 + }
1.1161 + }
1.1162 + }
1.1163 +
1.1164 +void CFbsBitGc::GetStrikethroughMetrics(TInt& aTop,TInt& aBottom)
1.1165 +/** Get the top and bottom of a strikethrough line for the current font, relative to the baseline.*/
1.1166 + {
1.1167 + aTop = -(iFont.AscentInPixels() * 5/12) - 1;
1.1168 + aBottom = aTop + Max(iFont.HeightInPixels() / 10,1);
1.1169 + }
1.1170 +
1.1171 +/** APIExtension can contain as many additional methods as is required by
1.1172 +CGraphicsContext after its original conception. It takes 3 parameters.
1.1173 +Function is exported due to constrains of retaining BC with earlier versions.
1.1174 +This is not used directly by external methods, instead it is called by a named
1.1175 +method in CGraphicsContext which passes the relivant arguements including an
1.1176 +unique identifier for the required action.
1.1177 +@param aUid The unique identifier for the method that is required. Selected
1.1178 +internally by a series of "if" statements.
1.1179 +@see Valid Uid identifiers are listed in header gdi.h
1.1180 +@see CGraphicsContext
1.1181 +@param aOutput is a TAny pointer to a reference. Used to output data as the structure
1.1182 +does not need to be instantiated before the function call this adds greater
1.1183 +flexibility.
1.1184 +@param aInput is a TAny pointer used to input data.
1.1185 +*/
1.1186 +EXPORT_C TInt CFbsBitGc::APIExtension(TUid aUid, TAny*& aOutput, TAny* aInput)
1.1187 + {
1.1188 + if (aUid == KGetUnderlineMetrics)
1.1189 + {
1.1190 + APIExGetUnderlineMetrics(aOutput);
1.1191 + return KErrNone;
1.1192 + }
1.1193 + else if (aUid == KSetShadowColor)
1.1194 + {
1.1195 + return APIExSetShadowColor(aInput);
1.1196 + }
1.1197 + else if (aUid == KGetShadowColor)
1.1198 + {
1.1199 + return APIExGetShadowColor(aOutput);
1.1200 + }
1.1201 + else if (aUid == KDrawTextInContextUid)
1.1202 + {
1.1203 + TDrawTextInContextInternal* contextParam = (TDrawTextInContextInternal*)aInput;
1.1204 + DrawText(contextParam->iText, &contextParam->iParam, contextParam->iPosition);
1.1205 + return KErrNone;
1.1206 + }
1.1207 + else if (aUid == KDrawBoxTextInContextUid)
1.1208 + {
1.1209 + TDrawTextInContextInternal* contextParam = (TDrawTextInContextInternal*)aInput;
1.1210 + DrawText(contextParam->iText,&contextParam->iParam,contextParam->iBox,contextParam->iBaselineOffset,contextParam->iAlign,contextParam->iMargin);
1.1211 + return KErrNone;
1.1212 + }
1.1213 + else if (aUid == KDrawTextInContextVerticalUid)
1.1214 + {
1.1215 + TDrawTextInContextInternal* contextParam = (TDrawTextInContextInternal*)aInput;
1.1216 + DrawTextVertical(contextParam->iText, &contextParam->iParam, contextParam->iPosition,contextParam->iUp);
1.1217 + return KErrNone;
1.1218 + }
1.1219 + else if (aUid == KDrawBoxTextInContextVerticalUid)
1.1220 + {
1.1221 + TDrawTextInContextInternal* contextParam = (TDrawTextInContextInternal*)aInput;
1.1222 + DrawTextVertical(contextParam->iText,&contextParam->iParam,contextParam->iBox,contextParam->iBaselineOffset,contextParam->iUp,contextParam->iAlign,contextParam->iMargin);
1.1223 + return KErrNone;
1.1224 + }
1.1225 + else if (aUid == KUidIsFbsBitmapGc)
1.1226 + {
1.1227 + return APIExIsFbsBitGc(aOutput);
1.1228 + }
1.1229 + /* Future cases may be placed here later.*/
1.1230 + else
1.1231 + return CBitmapContext::APIExtension(aUid, aOutput, aInput);
1.1232 + }
1.1233 +
1.1234 +
1.1235 +
1.1236 +
1.1237 +
1.1238 +
1.1239 +
1.1240 +
1.1241 +
1.1242 +//The methods listed above in APIExtension follow here with the prefix APIEx.
1.1243 +void CFbsBitGc::APIExGetUnderlineMetrics(TAny*& aOutput)
1.1244 + {
1.1245 + const TInt width = Max(iFont.HeightInPixels() / 10,1);
1.1246 + TTwoTInt* ptr = (TTwoTInt*)aOutput;
1.1247 + ptr->iTop = 1 + width / 2;
1.1248 + ptr->iBottom = (ptr->iTop) + width;
1.1249 + }
1.1250 +
1.1251 +TInt CFbsBitGc::APIExSetShadowColor(TAny* aShadowColor)
1.1252 + {
1.1253 + iFbsBitGcExtraData->SetShadowColor(*(reinterpret_cast<TRgb*>(aShadowColor)));
1.1254 + return KErrNone;
1.1255 + }
1.1256 +
1.1257 +TInt CFbsBitGc::APIExGetShadowColor(TAny*& aShadowColor)
1.1258 + {
1.1259 + TRgb* output = reinterpret_cast<TRgb*>(aShadowColor);
1.1260 + *output = iFbsBitGcExtraData->ShadowColor();
1.1261 + return KErrNone;
1.1262 + }
1.1263 +
1.1264 +TInt CFbsBitGc::APIExIsFbsBitGc(TAny*& aIsCFbsBitGc)
1.1265 + {
1.1266 + TBool *output = reinterpret_cast<TBool*>(aIsCFbsBitGc);
1.1267 + *output = ETrue;
1.1268 + return KErrNone;
1.1269 + }
1.1270 +
1.1271 +EXPORT_C void CFbsBitGc::DrawText(const TDesC& aText,const TTextParameters* aParam)
1.1272 + {
1.1273 + DrawText(aText,aParam,iLastPrintPosition,ELeft,CFont::EHorizontal);
1.1274 + }
1.1275 +
1.1276 +EXPORT_C void CFbsBitGc::DrawText(const TDesC& aText,const TTextParameters* aParam,const TPoint& aPosition)
1.1277 + {
1.1278 + DrawText(aText,aParam,aPosition,ELeft,CFont::EHorizontal);
1.1279 + }
1.1280 +
1.1281 +
1.1282 +EXPORT_C void CFbsBitGc::DrawText(const TDesC& aText,const TTextParameters* aParam,const TRect& aBox)
1.1283 + {
1.1284 + TRect boxcpy(aBox);
1.1285 + boxcpy.Move(iOrigin);
1.1286 + if(!iUserClipRect.Intersects(boxcpy)) return;
1.1287 + TRect oldcliprect(iUserClipRect);
1.1288 + iUserClipRect.Intersection(boxcpy);
1.1289 + DrawText(aText,aParam);
1.1290 + iUserClipRect=oldcliprect;
1.1291 + }
1.1292 +
1.1293 +EXPORT_C void CFbsBitGc::DrawText(const TDesC& aText,const TTextParameters* aParam,const TRect& aBox,TInt aBaselineOffset,TTextAlign aHrz,TInt aMargin)
1.1294 + {
1.1295 + DrawText(aText,aParam,aBox,aBaselineOffset,-1,aHrz,aMargin);
1.1296 + }
1.1297 +
1.1298 +EXPORT_C void CFbsBitGc::DrawText(const TDesC& aText,const TTextParameters* aParam,const TRect& aBox,TInt aBaselineOffset,TInt /*aTextWidth*/,TTextAlign aHrz,TInt aMargin)
1.1299 + {
1.1300 + // aTextWidth is not used here - try to abolish this - I think it is unneeded
1.1301 + TPoint p(aBox.iTl);
1.1302 + p.iY += aBaselineOffset;
1.1303 + switch (aHrz)
1.1304 + {
1.1305 + case ELeft: p.iX += aMargin; break;
1.1306 + case ERight: p.iX = aBox.iBr.iX - aMargin; break;
1.1307 + case ECenter: p.iX += aBox.Width() / 2 + aMargin; break;
1.1308 + }
1.1309 + DrawText(aText,aParam,p,aHrz,CFont::EHorizontal,&aBox);
1.1310 + }