/****************************************************************************** * ME_CharFromPointContext * * Returns a character position inside the run given a run-relative * pixel horizontal position. * * If closest is FALSE return the actual character * If closest is TRUE will round to the closest leading edge. * ie. if the second character is at pixel position 8 and third at 16 then for: * closest = FALSE cx = 0..7 return 0, cx = 8..15 return 1 * closest = TRUE cx = 0..3 return 0, cx = 4..11 return 1. */ int ME_CharFromPointContext(ME_Context *c, int cx, ME_Run *run, BOOL closest, BOOL visual_order) { ME_String *mask_text = NULL; WCHAR *str; int fit = 0; HGDIOBJ hOldFont; SIZE sz, sz2, sz3; if (!run->len || cx <= 0) return 0; if (run->nFlags & (MERF_TAB | MERF_ENDCELL)) { if (!closest || cx < run->nWidth / 2) return 0; return 1; } if (run->nFlags & MERF_GRAPHICS) { SIZE sz; ME_GetOLEObjectSize(c, run, &sz); if (!closest || cx < sz.cx / 2) return 0; return 1; } if (run->para->nFlags & MEPF_COMPLEX) { int cp, trailing; if (visual_order && run->script_analysis.fRTL) cx = run->nWidth - cx - 1; ScriptXtoCP( cx, run->len, run->num_glyphs, run->clusters, run->vis_attrs, run->advances, &run->script_analysis, &cp, &trailing ); TRACE("x %d cp %d trailing %d (run width %d) rtl %d log order %d\n", cx, cp, trailing, run->nWidth, run->script_analysis.fRTL, run->script_analysis.fLogicalOrder); return closest ? cp + trailing : cp; } if (c->editor->cPasswordMask) { mask_text = ME_MakeStringR( c->editor->cPasswordMask, run->len ); str = mask_text->szData; } else str = get_text( run, 0 ); hOldFont = ME_SelectStyleFont(c, run->style); GetTextExtentExPointW(c->hDC, str, run->len, cx, &fit, NULL, &sz); if (closest && fit != run->len) { GetTextExtentPoint32W(c->hDC, str, fit, &sz2); GetTextExtentPoint32W(c->hDC, str, fit + 1, &sz3); if (cx >= (sz2.cx+sz3.cx)/2) fit = fit + 1; } ME_DestroyString( mask_text ); ME_UnselectStyleFont(c, run->style, hOldFont); return fit; }
/****************************************************************************** * ME_GetTextExtent * * Finds a width and a height of the text using a specified style */ static void ME_GetTextExtent(ME_Context *c, LPCWSTR szText, int nChars, ME_Style *s, SIZE *size) { HGDIOBJ hOldFont; if (c->hDC) { hOldFont = ME_SelectStyleFont(c, s); GetTextExtentPoint32W(c->hDC, szText, nChars, size); ME_UnselectStyleFont(c, s, hOldFont); } else { size->cx = 0; size->cy = 0; } }
static void ME_DrawTextWithStyle(ME_Context *c, int x, int y, LPCWSTR szText, int nChars, ME_Style *s, int *width, int nSelFrom, int nSelTo, int ymin, int cy) { HDC hDC = c->hDC; HGDIOBJ hOldFont; COLORREF rgbOld, rgbBack; int yOffset = 0, yTwipsOffset = 0; hOldFont = ME_SelectStyleFont(c->editor, hDC, s); rgbBack = ME_GetBackColor(c->editor); if ((s->fmt.dwMask & CFM_COLOR) && (s->fmt.dwEffects & CFE_AUTOCOLOR)) rgbOld = SetTextColor(hDC, GetSysColor(COLOR_WINDOWTEXT)); else rgbOld = SetTextColor(hDC, s->fmt.crTextColor); if ((s->fmt.dwMask & s->fmt.dwEffects) & CFM_OFFSET) { yTwipsOffset = s->fmt.yOffset; } if ((s->fmt.dwMask & s->fmt.dwEffects) & (CFM_SUPERSCRIPT | CFM_SUBSCRIPT)) { if (s->fmt.dwEffects & CFE_SUPERSCRIPT) yTwipsOffset = s->fmt.yHeight/3; if (s->fmt.dwEffects & CFE_SUBSCRIPT) yTwipsOffset = -s->fmt.yHeight/12; } if (yTwipsOffset) { int numerator = 1; int denominator = 1; if (c->editor->nZoomNumerator) { numerator = c->editor->nZoomNumerator; denominator = c->editor->nZoomDenominator; } yOffset = yTwipsOffset * GetDeviceCaps(hDC, LOGPIXELSY) * numerator / denominator / 1440; } ExtTextOutW(hDC, x, y-yOffset, 0, NULL, szText, nChars, NULL); if (width) { SIZE sz; GetTextExtentPoint32W(hDC, szText, nChars, &sz); *width = sz.cx; } if (nSelFrom < nChars && nSelTo >= 0 && nSelFrom<nSelTo) { SIZE sz; if (nSelFrom < 0) nSelFrom = 0; if (nSelTo > nChars) nSelTo = nChars; GetTextExtentPoint32W(hDC, szText, nSelFrom, &sz); x += sz.cx; GetTextExtentPoint32W(hDC, szText+nSelFrom, nSelTo-nSelFrom, &sz); /* Invert selection if not hidden by EM_HIDESELECTION */ if (c->editor->bHideSelection == FALSE) PatBlt(hDC, x, ymin, sz.cx, cy, DSTINVERT); } SetTextColor(hDC, rgbOld); ME_UnselectStyleFont(c->editor, hDC, s, hOldFont); }
/****************************************************************************** * ME_CharFromPointContext * * Returns a character position inside the run given a run-relative * pixel horizontal position. * * If closest is FALSE return the actual character * If closest is TRUE will round to the closest leading edge. * ie. if the second character is at pixel position 8 and third at 16 then for: * closest = FALSE cx = 0..7 return 0, cx = 8..15 return 1 * closest = TRUE cx = 0..3 return 0, cx = 4..11 return 1. */ int ME_CharFromPointContext(ME_Context *c, int cx, ME_Run *run, BOOL closest, BOOL visual_order) { ME_String *mask_text = NULL; WCHAR *str; int fit = 0; HGDIOBJ hOldFont; SIZE sz, sz2, sz3; if (!run->len || cx <= 0) return 0; if (run->nFlags & (MERF_TAB | MERF_ENDCELL)) { if (!closest || cx < run->nWidth / 2) return 0; return 1; } if (run->nFlags & MERF_GRAPHICS) { SIZE sz; ME_GetOLEObjectSize(c, run, &sz); if (!closest || cx < sz.cx / 2) return 0; return 1; } if (c->editor->cPasswordMask) { mask_text = ME_MakeStringR( c->editor->cPasswordMask, run->len ); str = mask_text->szData; } else str = get_text( run, 0 ); hOldFont = ME_SelectStyleFont(c, run->style); GetTextExtentExPointW(c->hDC, str, run->len, cx, &fit, NULL, &sz); if (closest && fit != run->len) { GetTextExtentPoint32W(c->hDC, str, fit, &sz2); GetTextExtentPoint32W(c->hDC, str, fit + 1, &sz3); if (cx >= (sz2.cx+sz3.cx)/2) fit = fit + 1; } ME_DestroyString( mask_text ); ME_UnselectStyleFont(c, run->style, hOldFont); return fit; }
static HRESULT shape_run( ME_Context *c, ME_Run *run ) { HRESULT hr; HFONT old_font; int i; if (!run->glyphs) { run->max_glyphs = 1.5 * run->len + 16; /* This is suggested in the uniscribe documentation */ run->max_glyphs = (run->max_glyphs + 7) & ~7; /* Keep alignment simple */ get_run_glyph_buffers( run ); } if (run->max_clusters < run->len) { heap_free( run->clusters ); run->max_clusters = run->len * 2; run->clusters = heap_alloc( run->max_clusters * sizeof(WORD) ); } old_font = ME_SelectStyleFont( c, run->style ); while (1) { hr = ScriptShape( c->hDC, &run->style->script_cache, get_text( run, 0 ), run->len, run->max_glyphs, &run->script_analysis, run->glyphs, run->clusters, run->vis_attrs, &run->num_glyphs ); if (hr != E_OUTOFMEMORY) break; if (run->max_glyphs > 10 * run->len) break; /* something has clearly gone wrong */ run->max_glyphs *= 2; get_run_glyph_buffers( run ); } if (SUCCEEDED(hr)) hr = ScriptPlace( c->hDC, &run->style->script_cache, run->glyphs, run->num_glyphs, run->vis_attrs, &run->script_analysis, run->advances, run->offsets, NULL ); if (SUCCEEDED(hr)) { for (i = 0, run->nWidth = 0; i < run->num_glyphs; i++) run->nWidth += run->advances[i]; } ME_UnselectStyleFont( c, run->style, old_font ); return hr; }
void para_num_init( ME_Context *c, ME_Paragraph *para ) { ME_Style *style; CHARFORMAT2W cf; static const WCHAR bullet_font[] = {'S','y','m','b','o','l',0}; static const WCHAR bullet_str[] = {0xb7, 0}; static const WCHAR spaceW[] = {' ', 0}; HFONT old_font; SIZE sz; if (para->para_num.style && para->para_num.text) return; if (!para->para_num.style) { style = para->eop_run->style; cf.cbSize = sizeof(cf); cf.dwMask = CFM_FACE | CFM_CHARSET; memcpy( cf.szFaceName, bullet_font, sizeof(bullet_font) ); cf.bCharSet = SYMBOL_CHARSET; style = ME_ApplyStyle( c->editor, style, &cf ); para->para_num.style = style; } if (!para->para_num.text) { para->para_num.text = ME_MakeStringConst( bullet_str, 1 ); } old_font = ME_SelectStyleFont( c, para->para_num.style ); GetTextExtentPointW( c->hDC, para->para_num.text->szData, para->para_num.text->nLen, &sz ); para->para_num.width = sz.cx; GetTextExtentPointW( c->hDC, spaceW, 1, &sz ); para->para_num.width += sz.cx; ME_UnselectStyleFont( c, para->para_num.style, old_font ); }