Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(301)

Side by Side Diff: Source/platform/fonts/Font.cpp

Issue 676523003: Offset-only GlyphBuffer (Closed) Base URL: svn://svn.chromium.org/blink/trunk
Patch Set: review comments Created 6 years, 1 month ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
1 /* 1 /*
2 * Copyright (C) 1999 Lars Knoll (knoll@kde.org) 2 * Copyright (C) 1999 Lars Knoll (knoll@kde.org)
3 * (C) 1999 Antti Koivisto (koivisto@kde.org) 3 * (C) 1999 Antti Koivisto (koivisto@kde.org)
4 * (C) 2000 Dirk Mueller (mueller@kde.org) 4 * (C) 2000 Dirk Mueller (mueller@kde.org)
5 * Copyright (C) 2003, 2006, 2010, 2011 Apple Inc. All rights reserved. 5 * Copyright (C) 2003, 2006, 2010, 2011 Apple Inc. All rights reserved.
6 * Copyright (c) 2007, 2008, 2010 Google Inc. All rights reserved. 6 * Copyright (c) 2007, 2008, 2010 Google Inc. All rights reserved.
7 * 7 *
8 * This library is free software; you can redistribute it and/or 8 * This library is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU Library General Public 9 * modify it under the terms of the GNU Library General Public
10 * License as published by the Free Software Foundation; either 10 * License as published by the Free Software Foundation; either
(...skipping 90 matching lines...) Expand 10 before | Expand all | Expand 10 after
101 } 101 }
102 102
103 float Font::buildGlyphBuffer(const TextRunPaintInfo& runInfo, GlyphBuffer& glyph Buffer, 103 float Font::buildGlyphBuffer(const TextRunPaintInfo& runInfo, GlyphBuffer& glyph Buffer,
104 ForTextEmphasisOrNot forTextEmphasis) const 104 ForTextEmphasisOrNot forTextEmphasis) const
105 { 105 {
106 if (codePath(runInfo) == ComplexPath) { 106 if (codePath(runInfo) == ComplexPath) {
107 HarfBuzzShaper shaper(this, runInfo.run, (forTextEmphasis == ForTextEmph asis) 107 HarfBuzzShaper shaper(this, runInfo.run, (forTextEmphasis == ForTextEmph asis)
108 ? HarfBuzzShaper::ForTextEmphasis : HarfBuzzShaper::NotForTextEmphas is); 108 ? HarfBuzzShaper::ForTextEmphasis : HarfBuzzShaper::NotForTextEmphas is);
109 shaper.setDrawRange(runInfo.from, runInfo.to); 109 shaper.setDrawRange(runInfo.from, runInfo.to);
110 shaper.shape(&glyphBuffer); 110 shaper.shape(&glyphBuffer);
111 111 return shaper.totalWidth();
112 return 0;
113 } 112 }
114 113
115 SimpleShaper shaper(this, runInfo.run, nullptr /* fallbackFonts */, 114 SimpleShaper shaper(this, runInfo.run, nullptr /* fallbackFonts */,
116 nullptr /* GlyphBounds */, forTextEmphasis); 115 nullptr /* GlyphBounds */, forTextEmphasis);
117 shaper.advance(runInfo.from); 116 shaper.advance(runInfo.from);
118 float beforeWidth = shaper.runWidthSoFar();
119 shaper.advance(runInfo.to, &glyphBuffer); 117 shaper.advance(runInfo.to, &glyphBuffer);
118 float width = shaper.runWidthSoFar();
120 119
121 if (runInfo.run.ltr()) 120 if (runInfo.run.rtl()) {
122 return beforeWidth; 121 // Glyphs are shaped & stored in RTL advance order - reverse them for LT R drawing.
122 shaper.advance(runInfo.run.length());
123 glyphBuffer.reverseForSimpleRTL(width, shaper.runWidthSoFar());
124 }
123 125
124 // RTL 126 return width;
125 float afterWidth = shaper.runWidthSoFar();
126 shaper.advance(runInfo.run.length());
127 glyphBuffer.reverse();
128
129 return shaper.runWidthSoFar() - afterWidth;
130 } 127 }
131 128
132 void Font::drawText(GraphicsContext* context, const TextRunPaintInfo& runInfo, 129 void Font::drawText(GraphicsContext* context, const TextRunPaintInfo& runInfo,
133 const FloatPoint& point) const 130 const FloatPoint& point) const
134 { 131 {
135 // Don't draw anything while we are using custom fonts that are in the proce ss of loading. 132 // Don't draw anything while we are using custom fonts that are in the proce ss of loading.
136 if (shouldSkipDrawing()) 133 if (shouldSkipDrawing())
137 return; 134 return;
138 135
139 TextDrawingModeFlags textMode = context->textDrawingMode(); 136 TextDrawingModeFlags textMode = context->textDrawingMode();
140 if (!(textMode & TextModeFill) && !((textMode & TextModeStroke) && context-> hasStroke())) 137 if (!(textMode & TextModeFill) && !((textMode & TextModeStroke) && context-> hasStroke()))
141 return; 138 return;
142 139
143 if (runInfo.cachedTextBlob && runInfo.cachedTextBlob->get()) { 140 if (runInfo.cachedTextBlob && runInfo.cachedTextBlob->get()) {
144 ASSERT(RuntimeEnabledFeatures::textBlobEnabled()); 141 ASSERT(RuntimeEnabledFeatures::textBlobEnabled());
145 // we have a pre-cached blob -- happy joy! 142 // we have a pre-cached blob -- happy joy!
146 drawTextBlob(context, runInfo.cachedTextBlob->get(), point.data()); 143 drawTextBlob(context, runInfo.cachedTextBlob->get(), point.data());
147 return; 144 return;
148 } 145 }
149 146
150 GlyphBuffer glyphBuffer; 147 GlyphBuffer glyphBuffer;
151 float initialAdvance = buildGlyphBuffer(runInfo, glyphBuffer); 148 buildGlyphBuffer(runInfo, glyphBuffer);
152 149
153 if (glyphBuffer.isEmpty()) 150 if (glyphBuffer.isEmpty())
154 return; 151 return;
155 152
156 if (RuntimeEnabledFeatures::textBlobEnabled()) { 153 if (RuntimeEnabledFeatures::textBlobEnabled()) {
157 // Enabling text-blobs forces the blob rendering path even for uncacheab le blobs. 154 // Enabling text-blobs forces the blob rendering path even for uncacheab le blobs.
158 TextBlobPtr uncacheableTextBlob; 155 TextBlobPtr uncacheableTextBlob;
159 TextBlobPtr& textBlob = runInfo.cachedTextBlob ? *runInfo.cachedTextBlob : uncacheableTextBlob; 156 TextBlobPtr& textBlob = runInfo.cachedTextBlob ? *runInfo.cachedTextBlob : uncacheableTextBlob;
160 FloatRect blobBounds = runInfo.bounds; 157 FloatRect blobBounds = runInfo.bounds;
161 blobBounds.moveBy(-point); 158 blobBounds.moveBy(-point);
162 159
163 textBlob = buildTextBlob(glyphBuffer, initialAdvance, blobBounds, contex t->couldUseLCDRenderedText()); 160 textBlob = buildTextBlob(glyphBuffer, blobBounds, context->couldUseLCDRe nderedText());
164 if (textBlob) { 161 if (textBlob) {
165 drawTextBlob(context, textBlob.get(), point.data()); 162 drawTextBlob(context, textBlob.get(), point.data());
166 return; 163 return;
167 } 164 }
168 } 165 }
169 166
170 drawGlyphBuffer(context, runInfo, glyphBuffer, FloatPoint(point.x() + initia lAdvance, point.y())); 167 drawGlyphBuffer(context, runInfo, glyphBuffer, point);
171 } 168 }
172 169
173 float Font::drawUncachedText(GraphicsContext* context, const TextRunPaintInfo& r unInfo, 170 float Font::drawUncachedText(GraphicsContext* context, const TextRunPaintInfo& r unInfo,
174 const FloatPoint& point, CustomFontNotReadyAction customFontNotReadyAction) const 171 const FloatPoint& point, CustomFontNotReadyAction customFontNotReadyAction) const
175 { 172 {
176 // Don't draw anything while we are using custom fonts that are in the proce ss of loading, 173 // Don't draw anything while we are using custom fonts that are in the proce ss of loading,
177 // except if the 'force' argument is set to true (in which case it will use a fallback 174 // except if the 'force' argument is set to true (in which case it will use a fallback
178 // font). 175 // font).
179 if (shouldSkipDrawing() && customFontNotReadyAction == DoNotPaintIfFontNotRe ady) 176 if (shouldSkipDrawing() && customFontNotReadyAction == DoNotPaintIfFontNotRe ady)
180 return 0; 177 return 0;
181 178
182 TextDrawingModeFlags textMode = context->textDrawingMode(); 179 TextDrawingModeFlags textMode = context->textDrawingMode();
183 if (!(textMode & TextModeFill) && !((textMode & TextModeStroke) && context-> hasStroke())) 180 if (!(textMode & TextModeFill) && !((textMode & TextModeStroke) && context-> hasStroke()))
184 return 0; 181 return 0;
185 182
186 GlyphBuffer glyphBuffer; 183 GlyphBuffer glyphBuffer;
187 float initialAdvance = buildGlyphBuffer(runInfo, glyphBuffer); 184 float totalAdvance = buildGlyphBuffer(runInfo, glyphBuffer);
188 185
189 if (glyphBuffer.isEmpty()) 186 if (glyphBuffer.isEmpty())
190 return 0; 187 return 0;
191 188
192 return drawGlyphBuffer(context, runInfo, glyphBuffer, FloatPoint(point.x() + initialAdvance, point.y())); 189 drawGlyphBuffer(context, runInfo, glyphBuffer, point);
190
191 return totalAdvance;
193 } 192 }
194 193
195 void Font::drawEmphasisMarks(GraphicsContext* context, const TextRunPaintInfo& r unInfo, const AtomicString& mark, const FloatPoint& point) const 194 void Font::drawEmphasisMarks(GraphicsContext* context, const TextRunPaintInfo& r unInfo, const AtomicString& mark, const FloatPoint& point) const
196 { 195 {
197 if (shouldSkipDrawing()) 196 if (shouldSkipDrawing())
198 return; 197 return;
199 198
200 GlyphBuffer glyphBuffer; 199 GlyphBuffer glyphBuffer;
201 float initialAdvance = buildGlyphBuffer(runInfo, glyphBuffer, ForTextEmphasi s); 200 buildGlyphBuffer(runInfo, glyphBuffer, ForTextEmphasis);
202 201
203 if (glyphBuffer.isEmpty()) 202 if (glyphBuffer.isEmpty())
204 return; 203 return;
205 204
206 drawEmphasisMarks(context, runInfo, glyphBuffer, mark, FloatPoint(point.x() + initialAdvance, point.y())); 205 drawEmphasisMarks(context, runInfo, glyphBuffer, mark, point);
207 } 206 }
208 207
209 static inline void updateGlyphOverflowFromBounds(const IntRectExtent& glyphBound s, 208 static inline void updateGlyphOverflowFromBounds(const IntRectExtent& glyphBound s,
210 const FontMetrics& fontMetrics, GlyphOverflow* glyphOverflow) 209 const FontMetrics& fontMetrics, GlyphOverflow* glyphOverflow)
211 { 210 {
212 glyphOverflow->top = std::max<int>(glyphOverflow->top, 211 glyphOverflow->top = std::max<int>(glyphOverflow->top,
213 glyphBounds.top() - (glyphOverflow->computeBounds ? 0 : fontMetrics.asce nt())); 212 glyphBounds.top() - (glyphOverflow->computeBounds ? 0 : fontMetrics.asce nt()));
214 glyphOverflow->bottom = std::max<int>(glyphOverflow->bottom, 213 glyphOverflow->bottom = std::max<int>(glyphOverflow->bottom,
215 glyphBounds.bottom() - (glyphOverflow->computeBounds ? 0 : fontMetrics.d escent())); 214 glyphBounds.bottom() - (glyphOverflow->computeBounds ? 0 : fontMetrics.d escent()));
216 glyphOverflow->left = glyphBounds.left(); 215 glyphOverflow->left = glyphBounds.left();
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after
252 if (cacheEntry && (!fallbackFonts || fallbackFonts->isEmpty())) { 251 if (cacheEntry && (!fallbackFonts || fallbackFonts->isEmpty())) {
253 cacheEntry->glyphBounds = glyphBounds; 252 cacheEntry->glyphBounds = glyphBounds;
254 cacheEntry->width = result; 253 cacheEntry->width = result;
255 } 254 }
256 255
257 if (glyphOverflow) 256 if (glyphOverflow)
258 updateGlyphOverflowFromBounds(glyphBounds, fontMetrics(), glyphOverflow) ; 257 updateGlyphOverflowFromBounds(glyphBounds, fontMetrics(), glyphOverflow) ;
259 return result; 258 return result;
260 } 259 }
261 260
262 namespace { 261 PassTextBlobPtr Font::buildTextBlob(const GlyphBuffer& glyphBuffer, const FloatR ect& bounds,
262 bool couldUseLCD) const
263 {
264 ASSERT(RuntimeEnabledFeatures::textBlobEnabled());
263 265
264 template <bool hasOffsets> 266 SkTextBlobBuilder builder;
265 bool buildTextBlobInternal(const GlyphBuffer& glyphBuffer, SkScalar initialAdvan ce, 267 SkRect skBounds = bounds;
266 const SkRect* bounds, bool couldUseLCD, SkTextBlobBuilder& builder) 268 bool hasVerticalOffsets = glyphBuffer.hasVerticalOffsets();
267 { 269
268 SkScalar x = initialAdvance;
269 unsigned i = 0; 270 unsigned i = 0;
270 while (i < glyphBuffer.size()) { 271 while (i < glyphBuffer.size()) {
271 const SimpleFontData* fontData = glyphBuffer.fontDataAt(i); 272 const SimpleFontData* fontData = glyphBuffer.fontDataAt(i);
272 273
273 // FIXME: Handle vertical text. 274 // FIXME: Handle vertical text.
274 if (fontData->platformData().orientation() == Vertical) 275 if (fontData->platformData().orientation() == Vertical)
275 return false; 276 return nullptr;
276 277
277 // FIXME: FontPlatformData makes some decisions on the device scale 278 // FIXME: FontPlatformData makes some decisions on the device scale
278 // factor, which is found via the GraphicsContext. This should be fixed 279 // factor, which is found via the GraphicsContext. This should be fixed
279 // to avoid correctness problems here. 280 // to avoid correctness problems here.
280 SkPaint paint; 281 SkPaint paint;
281 fontData->platformData().setupPaint(&paint); 282 fontData->platformData().setupPaint(&paint);
282 paint.setTextEncoding(SkPaint::kGlyphID_TextEncoding); 283 paint.setTextEncoding(SkPaint::kGlyphID_TextEncoding);
283 284
284 // FIXME: this should go away after the big LCD cleanup. 285 // FIXME: this should go away after the big LCD cleanup.
285 paint.setLCDRenderText(paint.isLCDRenderText() && couldUseLCD); 286 paint.setLCDRenderText(paint.isLCDRenderText() && couldUseLCD);
286 287
287 unsigned start = i++; 288 unsigned start = i++;
288 while (i < glyphBuffer.size() && glyphBuffer.fontDataAt(i) == fontData) 289 while (i < glyphBuffer.size() && glyphBuffer.fontDataAt(i) == fontData)
289 i++; 290 i++;
290 unsigned count = i - start; 291 unsigned count = i - start;
291 292
292 const SkTextBlobBuilder::RunBuffer& buffer = hasOffsets ? 293 const SkTextBlobBuilder::RunBuffer& buffer = hasVerticalOffsets
293 builder.allocRunPos(paint, count, bounds) : 294 ? builder.allocRunPos(paint, count, &skBounds)
294 builder.allocRunPosH(paint, count, 0, bounds); 295 : builder.allocRunPosH(paint, count, 0, &skBounds);
295 296
296 const uint16_t* glyphs = glyphBuffer.glyphs(start); 297 const uint16_t* glyphs = glyphBuffer.glyphs(start);
298 const float* offsets = glyphBuffer.offsets(start);
297 std::copy(glyphs, glyphs + count, buffer.glyphs); 299 std::copy(glyphs, glyphs + count, buffer.glyphs);
300 std::copy(offsets, offsets + (hasVerticalOffsets ? 2 * count : count), b uffer.pos);
301 }
298 302
299 const float* advances = glyphBuffer.advances(start); 303 return adoptRef(builder.build());
300 const FloatSize* offsets = glyphBuffer.offsets(start);
301 for (unsigned j = 0; j < count; j++) {
302 if (hasOffsets) {
303 const FloatSize& offset = offsets[j];
304 buffer.pos[2 * j] = x + offset.width();
305 buffer.pos[2 * j + 1] = offset.height();
306 } else {
307 buffer.pos[j] = x;
308 }
309 x += SkFloatToScalar(advances[j]);
310 }
311 }
312 return true;
313 }
314
315 } // namespace
316
317 PassTextBlobPtr Font::buildTextBlob(const GlyphBuffer& glyphBuffer, float initia lAdvance,
318 const FloatRect& bounds, bool couldUseLCD) const
319 {
320 ASSERT(RuntimeEnabledFeatures::textBlobEnabled());
321
322 SkTextBlobBuilder builder;
323 SkScalar advance = SkFloatToScalar(initialAdvance);
324 SkRect skBounds = bounds;
325
326 bool success = glyphBuffer.hasOffsets() ?
327 buildTextBlobInternal<true>(glyphBuffer, advance, &skBounds, couldUseLCD , builder) :
328 buildTextBlobInternal<false>(glyphBuffer, advance, &skBounds, couldUseLC D, builder);
329 return success ? adoptRef(builder.build()) : nullptr;
330 } 304 }
331 305
332 static inline FloatRect pixelSnappedSelectionRect(FloatRect rect) 306 static inline FloatRect pixelSnappedSelectionRect(FloatRect rect)
333 { 307 {
334 // Using roundf() rather than ceilf() for the right edge as a compromise to 308 // Using roundf() rather than ceilf() for the right edge as a compromise to
335 // ensure correct caret positioning. 309 // ensure correct caret positioning.
336 float roundedX = roundf(rect.x()); 310 float roundedX = roundf(rect.x());
337 return FloatRect(roundedX, rect.y(), roundf(rect.maxX() - roundedX), rect.he ight()); 311 return FloatRect(roundedX, rect.y(), roundf(rect.maxX() - roundedX), rect.he ight());
338 } 312 }
339 313
(...skipping 467 matching lines...) Expand 10 before | Expand all | Expand 10 after
807 SkPaint paint = textFillPaint(gc, font); 781 SkPaint paint = textFillPaint(gc, font);
808 gc->drawPosTextH(glyphs, numGlyphs * sizeof(Glyph), xpos, constY, textRe ct, paint); 782 gc->drawPosTextH(glyphs, numGlyphs * sizeof(Glyph), xpos, constY, textRe ct, paint);
809 } 783 }
810 784
811 if ((textMode & TextModeStroke) && gc->hasStroke()) { 785 if ((textMode & TextModeStroke) && gc->hasStroke()) {
812 SkPaint paint = textStrokePaint(gc, font, textMode & TextModeFill); 786 SkPaint paint = textStrokePaint(gc, font, textMode & TextModeFill);
813 gc->drawPosTextH(glyphs, numGlyphs * sizeof(Glyph), xpos, constY, textRe ct, paint); 787 gc->drawPosTextH(glyphs, numGlyphs * sizeof(Glyph), xpos, constY, textRe ct, paint);
814 } 788 }
815 } 789 }
816 790
791 static void drawVerticalGlyphs(GraphicsContext* gc, const SimpleFontData* font,
792 const GlyphBuffer& glyphBuffer, unsigned from, unsigned numGlyphs, const Flo atPoint& point,
793 const FloatRect& textRect)
794 {
795 const OpenTypeVerticalData* verticalData = font->verticalData();
796
797 SkAutoSTMalloc<32, SkPoint> storage(numGlyphs);
798 SkPoint* pos = storage.get();
799
800 // Bend over backwards to preserve legacy rounding.
801 float initialAdvance = glyphBuffer.xOffsetAt(from);
802 FloatPoint adjustedPoint(point.x() + initialAdvance, point.y());
803
804 AffineTransform savedMatrix = gc->getCTM();
805 gc->concatCTM(AffineTransform(0, -1, 1, 0, adjustedPoint.x(), adjustedPoint. y()));
806 gc->concatCTM(AffineTransform(1, 0, 0, 1, -adjustedPoint.x(), -adjustedPoint .y()));
807
808 const unsigned kMaxBufferLength = 256;
809 Vector<FloatPoint, kMaxBufferLength> translations;
810
811 const FontMetrics& metrics = font->fontMetrics();
812 float verticalOriginX = adjustedPoint.x() + metrics.floatAscent() - metrics. floatAscent(IdeographicBaseline);
813
814 unsigned glyphIndex = 0;
815 while (glyphIndex < numGlyphs) {
816 unsigned chunkLength = std::min(kMaxBufferLength, numGlyphs - glyphIndex );
817
818 const Glyph* glyphs = glyphBuffer.glyphs(from + glyphIndex);
819
820 translations.resize(chunkLength);
821 verticalData->getVerticalTranslationsForGlyphs(font, glyphs, chunkLength ,
822 reinterpret_cast<float*>(&translations[0]));
823
824 for (unsigned i = 0; i < chunkLength; ++i, ++glyphIndex) {
825 SkScalar x = verticalOriginX + lroundf(translations[i].x());
826 SkScalar y = adjustedPoint.y() - SkIntToScalar(
827 -lroundf(glyphBuffer.xOffsetAt(from + glyphIndex) - initialAdvan ce - translations[i].y()));
828 pos[i].set(x, y);
829 }
830 paintGlyphs(gc, font, glyphs, chunkLength, pos, textRect);
831 }
832
833 gc->setCTM(savedMatrix);
834 }
835
817 void Font::drawGlyphs(GraphicsContext* gc, const SimpleFontData* font, 836 void Font::drawGlyphs(GraphicsContext* gc, const SimpleFontData* font,
818 const GlyphBuffer& glyphBuffer, unsigned from, unsigned numGlyphs, 837 const GlyphBuffer& glyphBuffer, unsigned from, unsigned numGlyphs,
819 const FloatPoint& point, const FloatRect& textRect) const 838 const FloatPoint& point, const FloatRect& textRect) const
820 { 839 {
821 SkScalar x = SkFloatToScalar(point.x()); 840 ASSERT(glyphBuffer.size() >= from + numGlyphs);
822 SkScalar y = SkFloatToScalar(point.y());
823 841
824 const OpenTypeVerticalData* verticalData = font->verticalData(); 842 if (font->platformData().orientation() == Vertical && font->verticalData()) {
825 if (font->platformData().orientation() == Vertical && verticalData) { 843 drawVerticalGlyphs(gc, font, glyphBuffer, from, numGlyphs, point, textRe ct);
826 SkAutoSTMalloc<32, SkPoint> storage(numGlyphs);
827 SkPoint* pos = storage.get();
828
829 AffineTransform savedMatrix = gc->getCTM();
830 gc->concatCTM(AffineTransform(0, -1, 1, 0, point.x(), point.y()));
831 gc->concatCTM(AffineTransform(1, 0, 0, 1, -point.x(), -point.y()));
832
833 const unsigned kMaxBufferLength = 256;
834 Vector<FloatPoint, kMaxBufferLength> translations;
835
836 const FontMetrics& metrics = font->fontMetrics();
837 SkScalar verticalOriginX = SkFloatToScalar(point.x() + metrics.floatAsce nt() - metrics.floatAscent(IdeographicBaseline));
838 float horizontalOffset = point.x();
839
840 unsigned glyphIndex = 0;
841 while (glyphIndex < numGlyphs) {
842 unsigned chunkLength = std::min(kMaxBufferLength, numGlyphs - glyphI ndex);
843
844 const Glyph* glyphs = glyphBuffer.glyphs(from + glyphIndex);
845 translations.resize(chunkLength);
846 verticalData->getVerticalTranslationsForGlyphs(font, &glyphs[0], chu nkLength, reinterpret_cast<float*>(&translations[0]));
847
848 x = verticalOriginX;
849 y = SkFloatToScalar(point.y() + horizontalOffset - point.x());
850
851 float currentWidth = 0;
852 for (unsigned i = 0; i < chunkLength; ++i, ++glyphIndex) {
853 pos[i].set(
854 x + SkIntToScalar(lroundf(translations[i].x())),
855 y + -SkIntToScalar(-lroundf(currentWidth - translations[i].y ())));
856 currentWidth += glyphBuffer.advanceAt(from + glyphIndex);
857 }
858 horizontalOffset += currentWidth;
859 paintGlyphs(gc, font, glyphs, chunkLength, pos, textRect);
860 }
861
862 gc->setCTM(savedMatrix);
863 return; 844 return;
864 } 845 }
865 846
866 if (!glyphBuffer.hasOffsets()) { 847 if (!glyphBuffer.hasVerticalOffsets()) {
867 SkAutoSTMalloc<64, SkScalar> storage(numGlyphs); 848 SkAutoSTMalloc<64, SkScalar> storage(numGlyphs);
868 SkScalar* xpos = storage.get(); 849 SkScalar* xpos = storage.get();
869 const float* adv = glyphBuffer.advances(from); 850 for (unsigned i = 0; i < numGlyphs; i++)
870 for (unsigned i = 0; i < numGlyphs; i++) { 851 xpos[i] = SkFloatToScalar(point.x() + glyphBuffer.xOffsetAt(from + i ));
871 xpos[i] = x; 852
872 x += SkFloatToScalar(adv[i]); 853 paintGlyphsHorizontal(gc, font, glyphBuffer.glyphs(from), numGlyphs, xpo s,
873 } 854 SkFloatToScalar(point.y()), textRect);
874 const Glyph* glyphs = glyphBuffer.glyphs(from);
875 paintGlyphsHorizontal(gc, font, glyphs, numGlyphs, xpos, SkFloatToScalar (y), textRect);
876 return; 855 return;
877 } 856 }
878 857
879 ASSERT(glyphBuffer.hasOffsets()); 858 ASSERT(glyphBuffer.hasVerticalOffsets());
880 SkAutoSTMalloc<32, SkPoint> storage(numGlyphs); 859 SkAutoSTMalloc<32, SkPoint> storage(numGlyphs);
881 SkPoint* pos = storage.get(); 860 SkPoint* pos = storage.get();
882 const FloatSize* offsets = glyphBuffer.offsets(from);
883 const float* advances = glyphBuffer.advances(from);
884 SkScalar advanceSoFar = SkFloatToScalar(0);
885 for (unsigned i = 0; i < numGlyphs; i++) { 861 for (unsigned i = 0; i < numGlyphs; i++) {
886 pos[i].set( 862 pos[i].set(
887 x + SkFloatToScalar(offsets[i].width()) + advanceSoFar, 863 SkFloatToScalar(point.x() + glyphBuffer.xOffsetAt(from + i)),
888 y + SkFloatToScalar(offsets[i].height())); 864 SkFloatToScalar(point.y() + glyphBuffer.yOffsetAt(from + i)));
889 advanceSoFar += SkFloatToScalar(advances[i]);
890 } 865 }
891 866
892 const Glyph* glyphs = glyphBuffer.glyphs(from); 867 paintGlyphs(gc, font, glyphBuffer.glyphs(from), numGlyphs, pos, textRect);
893 paintGlyphs(gc, font, glyphs, numGlyphs, pos, textRect);
894 } 868 }
895 869
896 void Font::drawTextBlob(GraphicsContext* gc, const SkTextBlob* blob, const SkPoi nt& origin) const 870 void Font::drawTextBlob(GraphicsContext* gc, const SkTextBlob* blob, const SkPoi nt& origin) const
897 { 871 {
898 ASSERT(RuntimeEnabledFeatures::textBlobEnabled()); 872 ASSERT(RuntimeEnabledFeatures::textBlobEnabled());
899 873
900 TextDrawingModeFlags textMode = gc->textDrawingMode(); 874 TextDrawingModeFlags textMode = gc->textDrawingMode();
901 if (textMode & TextModeFill) 875 if (textMode & TextModeFill)
902 gc->drawTextBlob(blob, origin, gc->fillPaint()); 876 gc->drawTextBlob(blob, origin, gc->fillPaint());
903 877
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after
936 // Return the rectangle for selecting the given range of code-points in the Text Run. 910 // Return the rectangle for selecting the given range of code-points in the Text Run.
937 FloatRect Font::selectionRectForComplexText(const TextRun& run, 911 FloatRect Font::selectionRectForComplexText(const TextRun& run,
938 const FloatPoint& point, int height, int from, int to) const 912 const FloatPoint& point, int height, int from, int to) const
939 { 913 {
940 HarfBuzzShaper shaper(this, run); 914 HarfBuzzShaper shaper(this, run);
941 if (!shaper.shape()) 915 if (!shaper.shape())
942 return FloatRect(); 916 return FloatRect();
943 return shaper.selectionRect(point, height, from, to); 917 return shaper.selectionRect(point, height, from, to);
944 } 918 }
945 919
946 float Font::drawGlyphBuffer(GraphicsContext* context, 920 void Font::drawGlyphBuffer(GraphicsContext* context,
947 const TextRunPaintInfo& runInfo, const GlyphBuffer& glyphBuffer, 921 const TextRunPaintInfo& runInfo, const GlyphBuffer& glyphBuffer,
948 const FloatPoint& point) const 922 const FloatPoint& point) const
949 { 923 {
950 // Draw each contiguous run of glyphs that use the same font data. 924 // Draw each contiguous run of glyphs that use the same font data.
951 const SimpleFontData* fontData = glyphBuffer.fontDataAt(0); 925 const SimpleFontData* fontData = glyphBuffer.fontDataAt(0);
952 FloatPoint startPoint(point);
953 float advanceSoFar = 0;
954 unsigned lastFrom = 0; 926 unsigned lastFrom = 0;
955 unsigned nextGlyph = 0; 927 unsigned nextGlyph;
956 928
957 while (nextGlyph < glyphBuffer.size()) { 929 for (nextGlyph = 0; nextGlyph < glyphBuffer.size(); ++nextGlyph) {
958 const SimpleFontData* nextFontData = glyphBuffer.fontDataAt(nextGlyph); 930 const SimpleFontData* nextFontData = glyphBuffer.fontDataAt(nextGlyph);
959 931
960 if (nextFontData != fontData) { 932 if (nextFontData != fontData) {
961 drawGlyphs(context, fontData, glyphBuffer, lastFrom, nextGlyph - las tFrom, startPoint, runInfo.bounds); 933 drawGlyphs(context, fontData, glyphBuffer, lastFrom, nextGlyph - las tFrom, point,
934 runInfo.bounds);
962 935
963 lastFrom = nextGlyph; 936 lastFrom = nextGlyph;
964 fontData = nextFontData; 937 fontData = nextFontData;
965 startPoint += FloatSize(advanceSoFar, 0);
966 advanceSoFar = 0;
967 } 938 }
968 advanceSoFar += glyphBuffer.advanceAt(nextGlyph);
969 nextGlyph++;
970 } 939 }
971 940
972 drawGlyphs(context, fontData, glyphBuffer, lastFrom, nextGlyph - lastFrom, s tartPoint, runInfo.bounds); 941 drawGlyphs(context, fontData, glyphBuffer, lastFrom, nextGlyph - lastFrom, p oint,
973 startPoint += FloatSize(advanceSoFar, 0); 942 runInfo.bounds);
974 return startPoint.x() - point.x();
975 } 943 }
976 944
977 inline static float offsetToMiddleOfGlyph(const SimpleFontData* fontData, Glyph glyph) 945 inline static float offsetToMiddleOfGlyph(const SimpleFontData* fontData, Glyph glyph)
978 { 946 {
979 if (fontData->platformData().orientation() == Horizontal) { 947 if (fontData->platformData().orientation() == Horizontal) {
980 FloatRect bounds = fontData->boundsForGlyph(glyph); 948 FloatRect bounds = fontData->boundsForGlyph(glyph);
981 return bounds.x() + bounds.width() / 2; 949 return bounds.x() + bounds.width() / 2;
982 } 950 }
983 // FIXME: Use glyph bounds once they make sense for vertical fonts. 951 // FIXME: Use glyph bounds once they make sense for vertical fonts.
984 return fontData->widthForGlyph(glyph) / 2; 952 return fontData->widthForGlyph(glyph) / 2;
985 } 953 }
986 954
987 inline static float offsetToMiddleOfAdvanceAtIndex(const GlyphBuffer& glyphBuffe r, size_t i)
988 {
989 return glyphBuffer.advanceAt(i) / 2;
990 }
991
992 void Font::drawEmphasisMarks(GraphicsContext* context, const TextRunPaintInfo& r unInfo, const GlyphBuffer& glyphBuffer, const AtomicString& mark, const FloatPoi nt& point) const 955 void Font::drawEmphasisMarks(GraphicsContext* context, const TextRunPaintInfo& r unInfo, const GlyphBuffer& glyphBuffer, const AtomicString& mark, const FloatPoi nt& point) const
993 { 956 {
994 FontCachePurgePreventer purgePreventer; 957 FontCachePurgePreventer purgePreventer;
995 958
996 GlyphData markGlyphData; 959 GlyphData markGlyphData;
997 if (!getEmphasisMarkGlyphData(mark, markGlyphData)) 960 if (!getEmphasisMarkGlyphData(mark, markGlyphData))
998 return; 961 return;
999 962
1000 const SimpleFontData* markFontData = markGlyphData.fontData; 963 const SimpleFontData* markFontData = markGlyphData.fontData;
1001 ASSERT(markFontData); 964 ASSERT(markFontData);
1002 if (!markFontData) 965 if (!markFontData)
1003 return; 966 return;
1004 967
1005 Glyph markGlyph = markGlyphData.glyph; 968 GlyphBuffer markBuffer;
1006 Glyph spaceGlyph = markFontData->spaceGlyph(); 969 float midMarkOffset = offsetToMiddleOfGlyph(markFontData, markGlyphData.glyp h);
970 for (unsigned i = 0; i < glyphBuffer.size(); ++i) {
971 // Skip marks for suppressed glyphs.
972 if (!glyphBuffer.glyphAt(i))
973 continue;
1007 974
1008 float middleOfLastGlyph = offsetToMiddleOfAdvanceAtIndex(glyphBuffer, 0); 975 // We want the middle of the emphasis mark aligned with the middle of th e glyph.
1009 FloatPoint startPoint(point.x() + middleOfLastGlyph - offsetToMiddleOfGlyph( markFontData, markGlyph), point.y()); 976 // The input offsets are already adjusted to point to the middle of the glyph, so all
977 // is left to do is adjust for 1/2 mark width.
978 // FIXME: we could avoid this by passing some additional info to the sha per,
979 // and perform all adjustments at buffer build time.
980 markBuffer.add(markGlyphData.glyph, markFontData, glyphBuffer.xOffsetAt( i) - midMarkOffset);
981 }
1010 982
1011 GlyphBuffer markBuffer; 983 drawGlyphBuffer(context, runInfo, markBuffer, point);
1012 for (unsigned i = 0; i + 1 < glyphBuffer.size(); ++i) {
1013 float middleOfNextGlyph = offsetToMiddleOfAdvanceAtIndex(glyphBuffer, i + 1);
1014 float advance = glyphBuffer.advanceAt(i) - middleOfLastGlyph + middleOfN extGlyph;
1015 markBuffer.add(glyphBuffer.glyphAt(i) ? markGlyph : spaceGlyph, markFont Data, advance);
1016 middleOfLastGlyph = middleOfNextGlyph;
1017 }
1018 markBuffer.add(glyphBuffer.glyphAt(glyphBuffer.size() - 1) ? markGlyph : spa ceGlyph, markFontData, 0);
1019
1020 drawGlyphBuffer(context, runInfo, markBuffer, startPoint);
1021 } 984 }
1022 985
1023 float Font::floatWidthForSimpleText(const TextRun& run, HashSet<const SimpleFont Data*>* fallbackFonts, IntRectExtent* glyphBounds) const 986 float Font::floatWidthForSimpleText(const TextRun& run, HashSet<const SimpleFont Data*>* fallbackFonts, IntRectExtent* glyphBounds) const
1024 { 987 {
1025 SimpleShaper::GlyphBounds bounds; 988 SimpleShaper::GlyphBounds bounds;
1026 SimpleShaper shaper(this, run, fallbackFonts, glyphBounds ? &bounds : 0); 989 SimpleShaper shaper(this, run, fallbackFonts, glyphBounds ? &bounds : 0);
1027 shaper.advance(run.length()); 990 shaper.advance(run.length());
1028 991
1029 if (glyphBounds) { 992 if (glyphBounds) {
1030 glyphBounds->setTop(floorf(-bounds.minGlyphBoundingBoxY)); 993 glyphBounds->setTop(floorf(-bounds.minGlyphBoundingBoxY));
(...skipping 65 matching lines...) Expand 10 before | Expand all | Expand 10 after
1096 if (delta <= 0) 1059 if (delta <= 0)
1097 break; 1060 break;
1098 } 1061 }
1099 } 1062 }
1100 } 1063 }
1101 1064
1102 return offset; 1065 return offset;
1103 } 1066 }
1104 1067
1105 } // namespace blink 1068 } // namespace blink
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698