📄 fontcgwin.cpp
字号:
/* * Copyright (C) 2006, 2007, 2008, 2009 Apple Inc. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */#include "config.h"#include "Font.h"#include "TransformationMatrix.h"#include "FloatConversion.h"#include "GlyphBuffer.h"#include "GraphicsContext.h"#include "IntRect.h"#include "SimpleFontData.h"#include "UniscribeController.h"#include "WebCoreTextRenderer.h"#include <ApplicationServices/ApplicationServices.h>#include <WebKitSystemInterface/WebKitSystemInterface.h>#include <wtf/MathExtras.h>namespace WebCore {const int syntheticObliqueAngle = 14;static inline CGFloat toCGFloat(FIXED f){ return f.value + f.fract / CGFloat(65536.0);}static CGPathRef createPathForGlyph(HDC hdc, Glyph glyph){ CGMutablePathRef path = CGPathCreateMutable(); static const MAT2 identity = { 0, 1, 0, 0, 0, 0, 0, 1 }; GLYPHMETRICS glyphMetrics; // GGO_NATIVE matches the outline perfectly when Windows font smoothing is off. // GGO_NATIVE | GGO_UNHINTED does not match perfectly either when Windows font smoothing is on or off. DWORD outlineLength = GetGlyphOutline(hdc, glyph, GGO_GLYPH_INDEX | GGO_NATIVE, &glyphMetrics, 0, 0, &identity); ASSERT(outlineLength >= 0); if (outlineLength < 0) return path; Vector<UInt8> outline(outlineLength); GetGlyphOutline(hdc, glyph, GGO_GLYPH_INDEX | GGO_NATIVE, &glyphMetrics, outlineLength, outline.data(), &identity); unsigned offset = 0; while (offset < outlineLength) { LPTTPOLYGONHEADER subpath = reinterpret_cast<LPTTPOLYGONHEADER>(outline.data() + offset); ASSERT(subpath->dwType == TT_POLYGON_TYPE); if (subpath->dwType != TT_POLYGON_TYPE) return path; CGPathMoveToPoint(path, 0, toCGFloat(subpath->pfxStart.x), toCGFloat(subpath->pfxStart.y)); unsigned subpathOffset = sizeof(*subpath); while (subpathOffset < subpath->cb) { LPTTPOLYCURVE segment = reinterpret_cast<LPTTPOLYCURVE>(reinterpret_cast<UInt8*>(subpath) + subpathOffset); switch (segment->wType) { case TT_PRIM_LINE: for (unsigned i = 0; i < segment->cpfx; i++) CGPathAddLineToPoint(path, 0, toCGFloat(segment->apfx[i].x), toCGFloat(segment->apfx[i].y)); break; case TT_PRIM_QSPLINE: for (unsigned i = 0; i < segment->cpfx; i++) { CGFloat x = toCGFloat(segment->apfx[i].x); CGFloat y = toCGFloat(segment->apfx[i].y); CGFloat cpx; CGFloat cpy; if (i == segment->cpfx - 2) { cpx = toCGFloat(segment->apfx[i + 1].x); cpy = toCGFloat(segment->apfx[i + 1].y); i++; } else { cpx = (toCGFloat(segment->apfx[i].x) + toCGFloat(segment->apfx[i + 1].x)) / 2; cpy = (toCGFloat(segment->apfx[i].y) + toCGFloat(segment->apfx[i + 1].y)) / 2; } CGPathAddQuadCurveToPoint(path, 0, x, y, cpx, cpy); } break; case TT_PRIM_CSPLINE: for (unsigned i = 0; i < segment->cpfx; i += 3) { CGFloat cp1x = toCGFloat(segment->apfx[i].x); CGFloat cp1y = toCGFloat(segment->apfx[i].y); CGFloat cp2x = toCGFloat(segment->apfx[i + 1].x); CGFloat cp2y = toCGFloat(segment->apfx[i + 1].y); CGFloat x = toCGFloat(segment->apfx[i + 2].x); CGFloat y = toCGFloat(segment->apfx[i + 2].y); CGPathAddCurveToPoint(path, 0, cp1x, cp1y, cp2x, cp2y, x, y); } break; default: ASSERT_NOT_REACHED(); return path; } subpathOffset += sizeof(*segment) + (segment->cpfx - 1) * sizeof(segment->apfx[0]); } CGPathCloseSubpath(path); offset += subpath->cb; } return path;}static void drawGDIGlyphs(GraphicsContext* graphicsContext, const SimpleFontData* font, const GlyphBuffer& glyphBuffer, int from, int numGlyphs, const FloatPoint& point){ Color fillColor = graphicsContext->fillColor(); bool drawIntoBitmap = false; int drawingMode = graphicsContext->textDrawingMode(); if (drawingMode == cTextFill) { if (!fillColor.alpha()) return; drawIntoBitmap = fillColor.alpha() != 255 || graphicsContext->inTransparencyLayer(); if (!drawIntoBitmap) { IntSize size; int blur; Color color; graphicsContext->getShadow(size, blur, color); drawIntoBitmap = !size.isEmpty() || blur; } } // We have to convert CG's two-dimensional floating point advances to just horizontal integer advances. Vector<int, 2048> gdiAdvances; int totalWidth = 0; for (int i = 0; i < numGlyphs; i++) { gdiAdvances.append(lroundf(glyphBuffer.advanceAt(from + i))); totalWidth += gdiAdvances[i]; } HDC hdc = 0; OwnPtr<GraphicsContext::WindowsBitmap> bitmap; IntRect textRect; if (!drawIntoBitmap) hdc = graphicsContext->getWindowsContext(textRect, true, false); if (!hdc) { drawIntoBitmap = true; // We put slop into this rect, since glyphs can overflow the ascent/descent bounds and the left/right edges. // FIXME: Can get glyphs' optical bounds (even from CG) to get this right. int lineGap = font->lineGap(); textRect = IntRect(point.x() - (font->ascent() + font->descent()) / 2, point.y() - font->ascent() - lineGap, totalWidth + font->ascent() + font->descent(), font->lineSpacing()); bitmap.set(graphicsContext->createWindowsBitmap(textRect.size())); memset(bitmap->buffer(), 255, bitmap->bufferLength()); hdc = bitmap->hdc(); XFORM xform; xform.eM11 = 1.0f; xform.eM12 = 0.0f; xform.eM21 = 0.0f; xform.eM22 = 1.0f; xform.eDx = -textRect.x(); xform.eDy = -textRect.y(); SetWorldTransform(hdc, &xform); }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -