微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

reactos操作系统实现(184)

GreExttextoutW函数实现一串字符串输出到指定区域,当然是从字符串变成图片输出。这些都调用FreeType库来实现的,具体实现代码如下:

#001 BOOL

#002 APIENTRY

#003 GreExttextoutW(

#004 IN HDC hDC,

#005 IN INT XStart,

#006 IN INT YStart,

#007 IN UINT fuOptions,

#008 IN OPTIONAL LPRECT lprc,

#009 IN LPWSTR String,

#010 IN INT Count,

#011 IN OPTIONAL LPINT Dx,

#012 IN DWORD dwCodePage)

#013 {

#014 /*

#015 * FIXME:

#016 * Call Engtextout,which does the real work (calling Drvtextout where

#017 * appropriate)

#018 */

#019

#020 DC *dc;

#021 PDC_ATTR Dc_Attr;

#022 SURFOBJ *SurfObj;

#023 SURFACE *psurf = NULL;

#024 int error,glyph_index,n,i;

#025 FT_Face face;

#026 FT_GlyphSlot glyph;

#027 FT_Glyph realglyph;

#028 FT_BitmapGlyph realglyph2;

#029 LONGLONG TextLeft,RealXStart;

#030 ULONG TextTop,prevIoUs,BackgroundLeft;

#031 FT_Bool use_kerning;

#032 RECTL DestRect,MaskRect;

#033 POINTL SourcePoint,BrushOrigin;

#034 HBrush hBrushFg = NULL;

#035 PGDIBrushOBJ BrushFg = NULL;

#036 GDIBrushINST BrushFgInst;

#037 HBrush hBrushBg = NULL;

#038 PGDIBrushOBJ BrushBg = NULL;

#039 GDIBrushINST BrushBgInst;

#040 HBITMAP HSourceGlyph;

#041 SURFOBJ *SourceGlyphSurf;

#042 SIZEL bitSize;

#043 FT_CharMap found = 0,charmap;

#044 INT yoff;

#045 FONTOBJ *FontObj;

#046 PFONTGDI FontGDI;

#047 PTEXTOBJ TextObj = NULL;

#048 PPALGDI PalDestGDI;

#049 XLATEOBJ *XlateObj=NULL,*XlateObj2=NULL;

#050 ULONG Mode;

#051 FT_Render_Mode RenderMode;

#052 BOOLEAN Render;

#053 POINT Start;

#054 BOOL dobreak = FALSE;

#055 HPALETTE hDestPalette;

#056 USHORT DxShift;

#057

#058 // Todo: Write test-cases to exactly match real Windows in different

#059 // bad parameters (e.g. does Windows check the DC or the RECT first?).

锁住输出设备。

#060 dc = DC_LockDc(hDC);

#061 if (!dc)

#062 {

#063 SetLastWin32Error(ERROR_INVALID_HANDLE);

#064 return FALSE;

#065 }

#066 if (dc->DC_Type == DC_TYPE_INFO)

#067 {

#068 DC_UnlockDc(dc);

#069 /* Yes,Windows really returns TRUE in this case */

#070 return TRUE;

#071 }

#072

获取设备的属性

#073 Dc_Attr = dc->pDc_Attr;

#074 if (!Dc_Attr) Dc_Attr = &dc->Dc_Attr;

#075

检查输出字符串是否有效,如果无效就直接返回。

#076 /* Check if String is valid */

#077 if ((Count > 0xFFFF) || (Count > 0 && String == NULL))

#078 {

#079 SetLastWin32Error(ERROR_INVALID_ParaMETER);

#080 goto fail;

#081 }

#082

#083 DxShift = fuOptions & eto_PDY ? 1 : 0;

#084

获取输出路径。

#085 if (PATH_IsPathOpen(dc->DcLevel))

#086 {

#087 if (!PATH_Exttextout( dc,

#088 XStart,

#089 YStart,

#090 fuOptions,

#091 (const RECT *)lprc,

#092 String,

#093 Count,

#094 (const INT *)Dx)) goto fail;

#095 goto good;

#096 }

#097

转换逻辑坐标为设备坐标。

#098 if (lprc && (fuOptions & (eto_OPAQUE | eto_CLIPPED)))

#099 {

#100 IntLPtoDP(dc,(POINT *)lprc,2);

#101 }

#102

获取设备输出的表面层缓冲区。

#103 psurf = SURFACE_LockSurface(dc->w.hBitmap);

#104 if (!psurf)

#105 {

#106 goto fail;

#107 }

#108 SurfObj = &psurf->SurfObj;

#109 ASSERT(SurfObj);

#110

#111 Start.x = XStart;

#112 Start.y = YStart;

#113 IntLPtoDP(dc,&Start,1);

#114

#115 RealXStart = (Start.x + dc->ptlDCOrig.x) << 6;

#116 YStart = Start.y + dc->ptlDCOrig.y;

#117

创建输出字符串的调色板。

#118 /* Create the brushes */

#119 hDestPalette = psurf->hDIBPalette;

#120 if (!hDestPalette) hDestPalette = pPrimarySurface->DevInfo.hpalDefault;

#121 PalDestGDI = PALETTE_LockPalette(hDestPalette);

#122 if ( !PalDestGDI )

#123 Mode = PAL_RGB;

#124 else

#125 {

#126 Mode = PalDestGDI->Mode;

#127 PALETTE_UnlockPalette(PalDestGDI);

#128 }

#129 XlateObj = (XLATEOBJ*)IntEngCreateXlate(Mode,PAL_RGB,hDestPalette,NULL);

#130 if ( !XlateObj )

#131 {

#132 goto fail;

#133 }

创建输出字体的画刷。

#134 hBrushFg = NtGdiCreateSolidBrush(XLATEOBJ_iXlate(XlateObj,Dc_Attr->crForegroundClr),0);

#135 if ( !hBrushFg )

#136 {

#137 goto fail;

#138 }

#139 BrushFg = BrushOBJ_LockBrush(hBrushFg);

#140 if ( !BrushFg )

#141 {

#142 goto fail;

#143 }

#144 IntGdiInitBrushInstance(&BrushFgInst,BrushFg,NULL);

#145 if ((fuOptions & eto_OPAQUE) || Dc_Attr->jBkMode == OPAQUE)

#146 {

#147 hBrushBg = NtGdiCreateSolidBrush(XLATEOBJ_iXlate(XlateObj,Dc_Attr->crBackgroundClr),0);

#148 if ( !hBrushBg )

#149 {

#150 goto fail;

#151 }

#152 BrushBg = BrushOBJ_LockBrush(hBrushBg);

#153 if ( !BrushBg )

#154 {

#155 goto fail;

#156 }

#157 IntGdiInitBrushInstance(&BrushBgInst,BrushBg,NULL);

#158 }

#159 XlateObj2 = (XLATEOBJ*)IntEngCreateXlate(PAL_RGB,Mode,NULL,hDestPalette);

#160 if ( !XlateObj2 )

#161 {

#162 goto fail;

#163 }

#164

#165 SourcePoint.x = 0;

#166 SourcePoint.y = 0;

#167 MaskRect.left = 0;

#168 MaskRect.top = 0;

#169 BrushOrigin.x = 0;

#170 BrushOrigin.y = 0;

#171

输出文本字符串前之前,用当前背景色更新输出区域。

#172 if ((fuOptions & eto_OPAQUE) && lprc)

#173 {

#174 DestRect.left = lprc->left + dc->ptlDCOrig.x;

#175 DestRect.top = lprc->top + dc->ptlDCOrig.y;

#176 DestRect.right = lprc->right + dc->ptlDCOrig.x;

#177 DestRect.bottom = lprc->bottom + dc->ptlDCOrig.y;

#178 IntLPtoDP(dc,(LPPOINT)&DestRect,2);

#179 IntEngBitBlt(

#180 &psurf->SurfObj,

#181 NULL,

#182 NULL,

#183 dc->CombinedClip,

#184 NULL,

#185 &DestRect,

#186 &SourcePoint,

#187 &SourcePoint,

#188 &BrushBgInst.BrushObject,

#189 &BrushOrigin,

#190 ROP3_TO_ROP4(PATcopY));

#191 fuOptions &= ~eto_OPAQUE;

#192 }

#193 else

#194 {

#195 if (Dc_Attr->jBkMode == OPAQUE)

#196 {

#197 fuOptions |= eto_OPAQUE;

#198 }

#199 }

#200

初始化字符串输出的字体。

#201 TextObj = Realizefontinit(Dc_Attr->hlfntNew);

#202 if (TextObj == NULL)

#203 {

#204 goto fail;

#205 }

#206

#207 FontObj = TextObj->Font;

#208 ASSERT(FontObj);

#209 FontGDI = ObjToGDI(FontObj,FONT);

#210 ASSERT(FontGDI);

#211

使用FREETYPE库来查找相应字符编码表。

#212 IntLockFreeType;

#213 face = FontGDI->face;

#214 if (face->charmap == NULL)

#215 {

#216 DPRINT("WARNING: No charmap selected!/n");

#217 DPRINT("This font face has %d charmaps/n",face->num_charmaps);

#218

#219 for (n = 0; n < face->num_charmaps; n++)

#220 {

#221 charmap = face->charmaps[n];

#222 DPRINT("found charmap encoding: %u/n",charmap->encoding);

#223 if (charmap->encoding != 0)

#224 {

#225 found = charmap;

#226 break;

#227 }

#228 }

#229 if (!found)

#230 {

#231 DPRINT1("WARNING: Could not find desired charmap!/n");

#232 }

#233 error = FT_Set_Charmap(face,found);

#234 if (error)

#235 {

#236 DPRINT1("WARNING: Could not set the charmap!/n");

#237 }

#238 }

#239

判断是单色字符显示,还是彩色图片显示

#240 Render = IntIsFontRenderingEnabled();

#241 if (Render)

#242 RenderMode = IntGetFontRenderMode(&TextObj->logfont.elfEnumLogfontEx.elfLogFont);

#243 else

#244 RenderMode = FT_RENDER_MODE_MONO;

#245

设置字体需像素点大小。

#246 error = FT_Set_Pixel_Sizes(

#247 face,

#248 TextObj->logfont.elfEnumLogfontEx.elfLogFont.lfWidth,

#249 /* FIXME should set character height if neg */

#250 (TextObj->logfont.elfEnumLogfontEx.elfLogFont.lfheight < 0 ?

#251 - TextObj->logfont.elfEnumLogfontEx.elfLogFont.lfheight :

#252 TextObj->logfont.elfEnumLogfontEx.elfLogFont.lfheight == 0 ? 11 : TextObj->logfont.elfEnumLogfontEx.elfLogFont.lfheight));

#253 if (error)

#254 {

#255 DPRINT1("Error in setting pixel sizes: %u/n",error);

#256 IntUnLockFreeType;

#257 goto fail;

#258 }

#259

#260 /*

#261 * Process the vertical alignment and determine the yoff.

#262 */

#263

处理每行字体的高度。

#264 if (Dc_Attr->lTextAlign & TA_BASELINE)

#265 yoff = 0;

#266 else if (Dc_Attr->lTextAlign & TA_BottOM)

#267 yoff = -face->size->metrics.descender >> 6;

#268 else /* TA_TOP */

#269 yoff = face->size->metrics.ascender >> 6;

#270

#271 use_kerning = FT_HAS_KERNING(face);

#272 prevIoUs = 0;

#273

#274 /*

#275 * Process the horizontal alignment and modify XStart accordingly.

#276 */

#277

处理字体宽度。

#278 if (Dc_Attr->lTextAlign & (TA_RIGHT | TA_CENTER))

#279 {

#280 ULONGLONG TextWidth = 0;

#281 LPCWSTR TempText = String;

#282 int Start;

#283

#284 /*

#285 * Calculate width of the text.

#286 */

#287

#288 if (NULL != Dx)

#289 {

#290 Start = Count < 2 ? 0 : Count - 2;

#291 TextWidth = Count < 2 ? 0 : (Dx[(Count-2)<<DxShift] << 6);

#292 }

#293 else

#294 {

#295 Start = 0;

#296 }

#297 TempText = String + Start;

#298

#299 for (i = Start; i < Count; i++)

#300 {

#301 if (fuOptions & eto_GLYPH_INDEX)

#302 glyph_index = *TempText;

#303 else

#304 glyph_index = FT_Get_Char_Index(face,*TempText);

#305

#306 if (!(realglyph = ftGdiGlyphCacheGet(face,

#307 TextObj->logfont.elfEnumLogfontEx.elfLogFont.lfheight)))

#308 {

#309 error = FT_Load_Glyph(face,FT_LOAD_DEFAULT);

#310 if (error)

#311 {

#312 DPRINT1("WARNING: Failed to load and render glyph! [index: %u]/n",glyph_index);

#313 }

#314

#315 glyph = face->glyph;

#316 realglyph = ftGdiGlyphCacheSet(face,

#317 TextObj->logfont.elfEnumLogfontEx.elfLogFont.lfheight,glyph,RenderMode);

#318 if (!realglyph)

#319 {

#320 DPRINT1("Failed to render glyph! [index: %u]/n",glyph_index);

#321 IntUnLockFreeType;

#322 goto fail;

#323 }

#324

#325 }

#326 /* retrieve kerning distance */

#327 if (use_kerning && prevIoUs && glyph_index)

#328 {

#329 FT_Vector delta;

#330 FT_Get_Kerning(face,&delta);

#331 TextWidth += delta.x;

#332 }

#333

#334 TextWidth += realglyph->advance.x >> 10;

#335

#336 prevIoUs = glyph_index;

#337 TempText++;

#338 }

#339

#340 prevIoUs = 0;

#341

#342 if (Dc_Attr->lTextAlign & TA_RIGHT)

#343 {

#344 RealXStart -= TextWidth;

#345 }

#346 else

#347 {

#348 RealXStart -= TextWidth / 2;

#349 }

#350 }

#351

#352 TextLeft = RealXStart;

#353 TextTop = YStart;

#354 BackgroundLeft = (RealXStart + 32) >> 6;

#355

#356 /*

#357 * The main rendering loop.

#358 */

#359

这里循环处理显示一个字符,主要的过程就是读取一个字符的编码,然后根据编码到码表里找到字符的笔画,然后生成一个字符的BMP位图,再把每个字符位图输出,就可以显示相应的字符串了。

#360 for (i = 0; i < Count; i++)

#361 {

#362 if (fuOptions & eto_GLYPH_INDEX)

#363 glyph_index = *String;

#364 else

#365 glyph_index = FT_Get_Char_Index(face,*String);

#366

#367 if (!(realglyph = ftGdiGlyphCacheGet(face,

#368 TextObj->logfont.elfEnumLogfontEx.elfLogFont.lfheight)))

#369 {

#370 error = FT_Load_Glyph(face,FT_LOAD_DEFAULT);

#371 if (error)

#372 {

#373 DPRINT1("Failed to load and render glyph! [index: %u]/n",glyph_index);

#374 IntUnLockFreeType;

#375 goto fail;

#376 }

#377 glyph = face->glyph;

#378 realglyph = ftGdiGlyphCacheSet(face,

#379 glyph_index,

#380 TextObj->logfont.elfEnumLogfontEx.elfLogFont.lfheight,

#381 glyph,

#382 RenderMode);

#383 if (!realglyph)

#384 {

#385 DPRINT1("Failed to render glyph! [index: %u]/n",glyph_index);

#386 IntUnLockFreeType;

#387 goto fail;

#388 }

#389 }

#390 // DbgPrint("realglyph: %x/n",realglyph);

#391 // DbgPrint("TextLeft: %d/n",TextLeft);

#392

#393 /* retrieve kerning distance and move pen position */

#394 if (use_kerning && prevIoUs && glyph_index && NULL == Dx)

#395 {

#396 FT_Vector delta;

#397 FT_Get_Kerning(face,&delta);

#398 TextLeft += delta.x;

#399 }

#400 // DPRINT1("TextLeft: %d/n",TextLeft);

#401 // DPRINT1("TextTop: %d/n",TextTop);

#402

#403 if (realglyph->format == ft_glyph_format_outline)

#404 {

#405 DbgPrint("Should already be done/n");

#406 // error = FT_Render_Glyph(glyph,RenderMode);

#407 error = FT_Glyph_To_Bitmap(&realglyph,RenderMode,0);

#408 if (error)

#409 {

#410 DPRINT1("WARNING: Failed to render glyph!/n");

#411 goto fail;

#412 }

#413 }

#414 realglyph2 = (FT_BitmapGlyph)realglyph;

#415

#416 // DPRINT1("Pitch: %d/n",pitch);

#417 // DPRINT1("Advance: %d/n",realglyph->advance.x);

#418

#419 if (fuOptions & eto_OPAQUE)

#420 {

#421 DestRect.left = BackgroundLeft;

#422 DestRect.right = (TextLeft + (realglyph->advance.x >> 10) + 32) >> 6;

#423 DestRect.top = TextTop + yoff - ((face->size->metrics.ascender + 32) >> 6);

#424 DestRect.bottom = TextTop + yoff + ((32 - face->size->metrics.descender) >> 6);

#425 IntEngBitBlt(

#426 &psurf->SurfObj,

#427 NULL,

#428 NULL,

#429 dc->CombinedClip,

#430 NULL,

#431 &DestRect,

#432 &SourcePoint,

#433 &SourcePoint,

#434 &BrushBgInst.BrushObject,

#435 &BrushOrigin,

#436 ROP3_TO_ROP4(PATcopY));

#437 BackgroundLeft = DestRect.right;

#438 }

#439

#440 DestRect.left = ((TextLeft + 32) >> 6) + realglyph2->left;

#441 DestRect.right = DestRect.left + realglyph2->bitmap.width;

#442 DestRect.top = TextTop + yoff - realglyph2->top;

#443 DestRect.bottom = DestRect.top + realglyph2->bitmap.rows;

#444

#445 bitSize.cx = realglyph2->bitmap.width;

#446 bitSize.cy = realglyph2->bitmap.rows;

#447 MaskRect.right = realglyph2->bitmap.width;

#448 MaskRect.bottom = realglyph2->bitmap.rows;

#449

#450 /*

#451 * We should create the bitmap out of the loop at the biggest possible

#452 * glyph size. Then use memset with 0 to clear it and sourcerect to

#453 * limit the work of the transbitblt.

#454 *

#455 * FIXME: DIB bitmaps should have an lDelta which is a multiple of 4.

#456 * Here we pass in the pitch from the FreeType bitmap,which is not

#457 * guaranteed to be a multiple of 4. If it's not,we should expand

#458 * the FreeType bitmap to a temporary bitmap.

#459 */

#460

#461 HSourceGlyph = EngCreateBitmap(bitSize,realglyph2->bitmap.pitch,

#462 (realglyph2->bitmap.pixel_mode == ft_pixel_mode_grays) ?

#463 BMF_8BPP : BMF_1BPP,BMF_TOPDOWN,

#464 realglyph2->bitmap.buffer);

#465 if ( !HSourceGlyph )

#466 {

#467 DPRINT1("WARNING: EngLockSurface() Failed!/n");

#468 // FT_Done_Glyph(realglyph);

#469 IntUnLockFreeType;

#470 goto fail;

#471 }

#472 SourceGlyphSurf = EngLockSurface((HSURF)HSourceGlyph);

#473 if ( !SourceGlyphSurf )

#474 {

#475 EngDeleteSurface((HSURF)HSourceGlyph);

#476 DPRINT1("WARNING: EngLockSurface() Failed!/n");

#477 IntUnLockFreeType;

#478 goto fail;

#479 }

#480

#481 /*

#482 * Use the font data as a mask to paint onto the DCs surface using a

#483 * brush.

#484 */

#485

#486 if (lprc &&

#487 (fuOptions & eto_CLIPPED) &&

#488 DestRect.right >= lprc->right + dc->ptlDCOrig.x)

#489 {

#490 // We do the check '>=' instead of '>' to possibly save an iteration

#491 // through this loop,since it's breaking after the drawing is done,

#492 // and x is always incremented.

#493 DestRect.right = lprc->right + dc->ptlDCOrig.x;

#494 dobreak = TRUE;

#495 }

#496

#497 IntEngMaskBlt(

#498 SurfObj,

#499 SourceGlyphSurf,

#500 dc->CombinedClip,

#501 XlateObj,

#502 XlateObj2,

#503 &DestRect,

#504 &SourcePoint,

#505 (PPOINTL)&MaskRect,

#506 &BrushFgInst.BrushObject,

#507 &BrushOrigin);

#508

#509 EngUnlockSurface(SourceGlyphSurf);

#510 EngDeleteSurface((HSURF)HSourceGlyph);

#511

#512 if (dobreak)

#513 {

#514 break;

#515 }

#516

#517 if (NULL == Dx)

#518 {

#519 TextLeft += realglyph->advance.x >> 10;

#520 // DbgPrint("new TextLeft: %d/n",TextLeft);

#521 }

#522 else

#523 {

#524 TextLeft += Dx[i<<DxShift] << 6;

#525 // DbgPrint("new TextLeft2: %d/n",TextLeft);

#526 }

#527

#528 if (DxShift)

#529 {

#530 TextTop -= Dx[2 * i + 1] << 6;

#531 }

#532

#533 prevIoUs = glyph_index;

#534

#535 String++;

#536 }

#537

后面就是删除分配的资源。

#538 IntUnLockFreeType;

#539

#540 EngDeleteXlate(XlateObj);

#541 EngDeleteXlate(XlateObj2);

#542 SURFACE_UnlockSurface(psurf);

#543 if (TextObj != NULL)

#544 TEXTOBJ_UnlockText(TextObj);

#545 if (hBrushBg != NULL)

#546 {

#547 BrushOBJ_UnlockBrush(BrushBg);

#548 NtGdiDeleteObject(hBrushBg);

#549 }

#550 BrushOBJ_UnlockBrush(BrushFg);

#551 NtGdiDeleteObject(hBrushFg);

#552 good:

#553 DC_UnlockDc( dc );

#554

#555 return TRUE;

#556

#557 fail:

#558 if ( XlateObj2 != NULL )

#559 EngDeleteXlate(XlateObj2);

#560 if ( XlateObj != NULL )

#561 EngDeleteXlate(XlateObj);

#562 if (TextObj != NULL)

#563 TEXTOBJ_UnlockText(TextObj);

#564 if (psurf != NULL)

#565 SURFACE_UnlockSurface(psurf);

#566 if (hBrushBg != NULL)

#567 {

#568 BrushOBJ_UnlockBrush(BrushBg);

#569 NtGdiDeleteObject(hBrushBg);

#570 }

#571 if (hBrushFg != NULL)

#572 {

#573 BrushOBJ_UnlockBrush(BrushFg);

#574 NtGdiDeleteObject(hBrushFg);

#575 }

#576 DC_UnlockDc(dc);

#577

#578 return FALSE;

#579}

原文地址:https://www.jb51.cc/react/308336.html

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐