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

Side by Side Diff: sky/engine/platform/fonts/harfbuzz/FontHarfBuzz.cpp

Issue 859203002: Merge Blink code to cache SkTextBlob (Closed) Base URL: git@github.com:domokit/mojo.git@master
Patch Set: hashmap Created 5 years, 11 months 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
OLDNEW
1 /* 1 /*
2 * Copyright (c) 2007, 2008, 2010 Google Inc. All rights reserved. 2 * Copyright (c) 2007, 2008, 2010 Google Inc. All rights reserved.
3 * 3 *
4 * Redistribution and use in source and binary forms, with or without 4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions are 5 * modification, are permitted provided that the following conditions are
6 * met: 6 * met:
7 * 7 *
8 * * Redistributions of source code must retain the above copyright 8 * * Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer. 9 * notice, this list of conditions and the following disclaimer.
10 * * Redistributions in binary form must reproduce the above 10 * * Redistributions in binary form must reproduce the above
(...skipping 13 matching lines...) Expand all
24 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 24 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
25 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 25 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
26 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 26 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 27 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
28 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 28 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29 */ 29 */
30 30
31 #include "sky/engine/config.h" 31 #include "sky/engine/config.h"
32 #include "sky/engine/platform/fonts/Font.h" 32 #include "sky/engine/platform/fonts/Font.h"
33 33
34 #include "sky/engine/platform/NotImplemented.h" 34 #include "gen/sky/platform/RuntimeEnabledFeatures.h"
35 #include "sky/engine/platform/fonts/FontPlatformFeatures.h" 35 #include "sky/engine/platform/fonts/FontPlatformFeatures.h"
36 #include "sky/engine/platform/fonts/GlyphBuffer.h" 36 #include "sky/engine/platform/fonts/GlyphBuffer.h"
37 #include "sky/engine/platform/fonts/SimpleFontData.h" 37 #include "sky/engine/platform/fonts/SimpleFontData.h"
38 #include "sky/engine/platform/fonts/harfbuzz/HarfBuzzShaper.h" 38 #include "sky/engine/platform/fonts/harfbuzz/HarfBuzzShaper.h"
39 #include "sky/engine/platform/geometry/FloatRect.h" 39 #include "sky/engine/platform/geometry/FloatRect.h"
40 #include "sky/engine/platform/graphics/GraphicsContext.h" 40 #include "sky/engine/platform/graphics/GraphicsContext.h"
41 41
42 #include "third_party/skia/include/core/SkPaint.h" 42 #include "third_party/skia/include/core/SkPaint.h"
43 #include "third_party/skia/include/core/SkTemplates.h" 43 #include "third_party/skia/include/core/SkTemplates.h"
44 44
(...skipping 105 matching lines...) Expand 10 before | Expand all | Expand 10 after
150 verticalData->getVerticalTranslationsForGlyphs(font, &glyphs[0], chu nkLength, reinterpret_cast<float*>(&translations[0])); 150 verticalData->getVerticalTranslationsForGlyphs(font, &glyphs[0], chu nkLength, reinterpret_cast<float*>(&translations[0]));
151 151
152 x = verticalOriginX; 152 x = verticalOriginX;
153 y = SkFloatToScalar(point.y() + horizontalOffset - point.x()); 153 y = SkFloatToScalar(point.y() + horizontalOffset - point.x());
154 154
155 float currentWidth = 0; 155 float currentWidth = 0;
156 for (unsigned i = 0; i < chunkLength; ++i, ++glyphIndex) { 156 for (unsigned i = 0; i < chunkLength; ++i, ++glyphIndex) {
157 pos[i].set( 157 pos[i].set(
158 x + SkIntToScalar(lroundf(translations[i].x())), 158 x + SkIntToScalar(lroundf(translations[i].x())),
159 y + -SkIntToScalar(-lroundf(currentWidth - translations[i].y ()))); 159 y + -SkIntToScalar(-lroundf(currentWidth - translations[i].y ())));
160 currentWidth += glyphBuffer.advanceAt(from + glyphIndex).width() ; 160 currentWidth += glyphBuffer.advanceAt(from + glyphIndex);
161 } 161 }
162 horizontalOffset += currentWidth; 162 horizontalOffset += currentWidth;
163 paintGlyphs(gc, font, glyphs, chunkLength, pos, textRect); 163 paintGlyphs(gc, font, glyphs, chunkLength, pos, textRect);
164 } 164 }
165 165
166 gc->setCTM(savedMatrix); 166 gc->setCTM(savedMatrix);
167 return; 167 return;
168 } 168 }
169 169
170 if (!glyphBuffer.hasVerticalAdvances()) { 170 if (!glyphBuffer.hasOffsets()) {
171 SkAutoSTMalloc<64, SkScalar> storage(numGlyphs); 171 SkAutoSTMalloc<64, SkScalar> storage(numGlyphs);
172 SkScalar* xpos = storage.get(); 172 SkScalar* xpos = storage.get();
173 const FloatSize* adv = glyphBuffer.advances(from); 173 const float* adv = glyphBuffer.advances(from);
174 for (unsigned i = 0; i < numGlyphs; i++) { 174 for (unsigned i = 0; i < numGlyphs; i++) {
175 xpos[i] = x; 175 xpos[i] = x;
176 x += SkFloatToScalar(adv[i].width()); 176 x += SkFloatToScalar(adv[i]);
177 } 177 }
178 const Glyph* glyphs = glyphBuffer.glyphs(from); 178 const Glyph* glyphs = glyphBuffer.glyphs(from);
179 paintGlyphsHorizontal(gc, font, glyphs, numGlyphs, xpos, SkFloatToScalar (y), textRect); 179 paintGlyphsHorizontal(gc, font, glyphs, numGlyphs, xpos, SkFloatToScalar (y), textRect);
180 return; 180 return;
181 } 181 }
182 182
183 // FIXME: text rendering speed: 183 // FIXME: text rendering speed:
184 // Android has code in their WebCore fork to special case when the 184 // Android has code in their WebCore fork to special case when the
185 // GlyphBuffer has no advances other than the defaults. In that case the 185 // GlyphBuffer has no advances other than the defaults. In that case the
186 // text drawing can proceed faster. However, it's unclear when those 186 // text drawing can proceed faster. However, it's unclear when those
187 // patches may be upstreamed to WebKit so we always use the slower path 187 // patches may be upstreamed to WebKit so we always use the slower path
188 // here. 188 // here.
189 SkAutoSTMalloc<32, SkPoint> storage(numGlyphs); 189 SkAutoSTMalloc<32, SkPoint> storage(numGlyphs);
190 SkPoint* pos = storage.get(); 190 SkPoint* pos = storage.get();
191 const FloatSize* adv = glyphBuffer.advances(from); 191 const FloatSize* offsets = glyphBuffer.offsets(from);
192 const float* advances = glyphBuffer.advances(from);
193 SkScalar advanceSoFar = SkFloatToScalar(0);
192 for (unsigned i = 0; i < numGlyphs; i++) { 194 for (unsigned i = 0; i < numGlyphs; i++) {
193 pos[i].set(x, y); 195 pos[i].set(
194 x += SkFloatToScalar(adv[i].width()); 196 x + SkFloatToScalar(offsets[i].width()) + advanceSoFar,
195 y += SkFloatToScalar(adv[i].height()); 197 y + SkFloatToScalar(offsets[i].height()));
198 advanceSoFar += SkFloatToScalar(advances[i]);
196 } 199 }
197 200
198 const Glyph* glyphs = glyphBuffer.glyphs(from); 201 const Glyph* glyphs = glyphBuffer.glyphs(from);
199 paintGlyphs(gc, font, glyphs, numGlyphs, pos, textRect); 202 paintGlyphs(gc, font, glyphs, numGlyphs, pos, textRect);
200 } 203 }
201 204
202 void Font::drawTextBlob(GraphicsContext* gc, const SkTextBlob* blob, const SkPoi nt& origin) const 205 void Font::drawTextBlob(GraphicsContext* gc, const SkTextBlob* blob, const SkPoi nt& origin) const
203 { 206 {
207 ASSERT(RuntimeEnabledFeatures::textBlobEnabled());
208
204 // FIXME: It would be good to move this to Font.cpp, if we're sure that none 209 // FIXME: It would be good to move this to Font.cpp, if we're sure that none
205 // of the things in FontMac's setupPaint need to apply here. 210 // of the things in FontMac's setupPaint need to apply here.
206 // See also paintGlyphs. 211 // See also paintGlyphs.
207 TextDrawingModeFlags textMode = gc->textDrawingMode(); 212 TextDrawingModeFlags textMode = gc->textDrawingMode();
208 213
209 if (textMode & TextModeFill) { 214 if (textMode & TextModeFill)
210 SkPaint paint = gc->fillPaint(); 215 gc->drawTextBlob(blob, origin, gc->fillPaint());
211 gc->adjustTextRenderMode(&paint);
212 paint.setTextEncoding(SkPaint::kGlyphID_TextEncoding);
213 gc->drawTextBlob(blob, origin, paint);
214 }
215 216
216 if ((textMode & TextModeStroke) && gc->hasStroke()) { 217 if ((textMode & TextModeStroke) && gc->hasStroke()) {
217 SkPaint paint = gc->strokePaint(); 218 SkPaint paint = gc->strokePaint();
218 gc->adjustTextRenderMode(&paint);
219 paint.setTextEncoding(SkPaint::kGlyphID_TextEncoding);
220 if (textMode & TextModeFill) 219 if (textMode & TextModeFill)
221 paint.setLooper(0); 220 paint.setLooper(0);
222 gc->drawTextBlob(blob, origin, paint); 221 gc->drawTextBlob(blob, origin, paint);
223 } 222 }
224 } 223 }
225 224
226 void Font::drawComplexText(GraphicsContext* gc, const TextRunPaintInfo& runInfo, const FloatPoint& point) const
227 {
228 if (!runInfo.run.length())
229 return;
230
231 TextDrawingModeFlags textMode = gc->textDrawingMode();
232 bool fill = textMode & TextModeFill;
233 bool stroke = (textMode & TextModeStroke) && gc->hasStroke();
234
235 if (!fill && !stroke)
236 return;
237
238 GlyphBuffer glyphBuffer;
239 HarfBuzzShaper shaper(this, runInfo.run);
240 shaper.setDrawRange(runInfo.from, runInfo.to);
241 if (!shaper.shape(&glyphBuffer) || glyphBuffer.isEmpty())
242 return;
243 FloatPoint adjustedPoint = shaper.adjustStartPoint(point);
244 drawGlyphBuffer(gc, runInfo, glyphBuffer, adjustedPoint);
245 }
246
247 void Font::drawEmphasisMarksForComplexText(GraphicsContext* context, const TextR unPaintInfo& runInfo, const AtomicString& mark, const FloatPoint& point) const
248 {
249 GlyphBuffer glyphBuffer;
250
251 float initialAdvance = getGlyphsAndAdvancesForComplexText(runInfo, glyphBuff er, ForTextEmphasis);
252
253 if (glyphBuffer.isEmpty())
254 return;
255
256 drawEmphasisMarks(context, runInfo, glyphBuffer, mark, FloatPoint(point.x() + initialAdvance, point.y()));
257 }
258
259 float Font::getGlyphsAndAdvancesForComplexText(const TextRunPaintInfo& runInfo, GlyphBuffer& glyphBuffer, ForTextEmphasisOrNot forTextEmphasis) const
260 {
261 HarfBuzzShaper shaper(this, runInfo.run, HarfBuzzShaper::ForTextEmphasis);
262 shaper.setDrawRange(runInfo.from, runInfo.to);
263 shaper.shape(&glyphBuffer);
264 return 0;
265 }
266
267 float Font::floatWidthForComplexText(const TextRun& run, HashSet<const SimpleFon tData*>* fallbackFonts, IntRectExtent* glyphBounds) const 225 float Font::floatWidthForComplexText(const TextRun& run, HashSet<const SimpleFon tData*>* fallbackFonts, IntRectExtent* glyphBounds) const
268 { 226 {
269 HarfBuzzShaper shaper(this, run, HarfBuzzShaper::NotForTextEmphasis, fallbac kFonts); 227 HarfBuzzShaper shaper(this, run, HarfBuzzShaper::NotForTextEmphasis, fallbac kFonts);
270 if (!shaper.shape()) 228 if (!shaper.shape())
271 return 0; 229 return 0;
272 230
273 glyphBounds->setTop(floorf(-shaper.glyphBoundingBox().top())); 231 glyphBounds->setTop(floorf(-shaper.glyphBoundingBox().top()));
274 glyphBounds->setBottom(ceilf(shaper.glyphBoundingBox().bottom())); 232 glyphBounds->setBottom(ceilf(shaper.glyphBoundingBox().bottom()));
275 glyphBounds->setLeft(std::max<int>(0, floorf(-shaper.glyphBoundingBox().left ()))); 233 glyphBounds->setLeft(std::max<int>(0, floorf(-shaper.glyphBoundingBox().left ())));
276 glyphBounds->setRight(std::max<int>(0, ceilf(shaper.glyphBoundingBox().right () - shaper.totalWidth()))); 234 glyphBounds->setRight(std::max<int>(0, ceilf(shaper.glyphBoundingBox().right () - shaper.totalWidth())));
(...skipping 15 matching lines...) Expand all
292 FloatRect Font::selectionRectForComplexText(const TextRun& run, 250 FloatRect Font::selectionRectForComplexText(const TextRun& run,
293 const FloatPoint& point, int height, 251 const FloatPoint& point, int height,
294 int from, int to) const 252 int from, int to) const
295 { 253 {
296 HarfBuzzShaper shaper(this, run); 254 HarfBuzzShaper shaper(this, run);
297 if (!shaper.shape()) 255 if (!shaper.shape())
298 return FloatRect(); 256 return FloatRect();
299 return shaper.selectionRect(point, height, from, to); 257 return shaper.selectionRect(point, height, from, to);
300 } 258 }
301 259
302 PassTextBlobPtr Font::buildTextBlob(const GlyphBuffer& glyphBuffer, float initia lAdvance, const FloatRect& bounds) const 260 namespace {
261
262 template <bool hasOffsets>
263 bool buildTextBlobInternal(const GlyphBuffer& glyphBuffer, SkScalar initialAdvan ce, SkTextBlobBuilder& builder)
303 { 264 {
304 // FIXME: Except for setupPaint, this is not specific to FontHarfBuzz. 265 SkScalar x = initialAdvance;
305 // FIXME: Also implement the more general full-positioning path.
306 ASSERT(!glyphBuffer.hasVerticalAdvances());
307
308 SkTextBlobBuilder builder;
309 SkScalar x = SkFloatToScalar(initialAdvance);
310 SkRect skBounds = bounds;
311
312 unsigned i = 0; 266 unsigned i = 0;
313 while (i < glyphBuffer.size()) { 267 while (i < glyphBuffer.size()) {
314 const SimpleFontData* fontData = glyphBuffer.fontDataAt(i); 268 const SimpleFontData* fontData = glyphBuffer.fontDataAt(i);
315 269
316 // FIXME: Handle vertical text. 270 // FIXME: Handle vertical text.
317 if (fontData->platformData().orientation() == Vertical) 271 if (fontData->platformData().orientation() == Vertical)
318 return nullptr; 272 return false;
319 273
320 // FIXME: Handle SVG fonts. 274 // FIXME: Handle SVG fonts.
321 if (fontData->isSVGFont()) 275 if (fontData->isSVGFont())
322 return nullptr; 276 return false;
323 277
324 // FIXME: FontPlatformData makes some decisions on the device scale 278 // FIXME: FontPlatformData makes some decisions on the device scale
325 // factor, which is found via the GraphicsContext. This should be fixed 279 // factor, which is found via the GraphicsContext. This should be fixed
326 // to avoid correctness problems here. 280 // to avoid correctness problems here.
327 SkPaint paint; 281 SkPaint paint;
328 fontData->platformData().setupPaint(&paint); 282 fontData->platformData().setupPaint(&paint);
329 paint.setTextEncoding(SkPaint::kGlyphID_TextEncoding); 283 paint.setTextEncoding(SkPaint::kGlyphID_TextEncoding);
330 284
331 unsigned start = i++; 285 unsigned start = i++;
332 while (i < glyphBuffer.size() && glyphBuffer.fontDataAt(i) == fontData) 286 while (i < glyphBuffer.size() && glyphBuffer.fontDataAt(i) == fontData)
333 i++; 287 i++;
334 unsigned count = i - start; 288 unsigned count = i - start;
335 289
336 const SkTextBlobBuilder::RunBuffer& buffer = builder.allocRunPosH(paint, count, 0, &skBounds); 290 const SkTextBlobBuilder::RunBuffer& buffer = hasOffsets ?
291 builder.allocRunPos(paint, count) :
292 builder.allocRunPosH(paint, count, 0);
337 293
338 const uint16_t* glyphs = glyphBuffer.glyphs(start); 294 const uint16_t* glyphs = glyphBuffer.glyphs(start);
339 std::copy(glyphs, glyphs + count, buffer.glyphs); 295 std::copy(glyphs, glyphs + count, buffer.glyphs);
340 296
341 const FloatSize* advances = glyphBuffer.advances(start); 297 const float* advances = glyphBuffer.advances(start);
298 const FloatSize* offsets = glyphBuffer.offsets(start);
342 for (unsigned j = 0; j < count; j++) { 299 for (unsigned j = 0; j < count; j++) {
343 buffer.pos[j] = x; 300 if (hasOffsets) {
344 x += SkFloatToScalar(advances[j].width()); 301 const FloatSize& offset = offsets[j];
302 buffer.pos[2 * j] = x + offset.width();
303 buffer.pos[2 * j + 1] = offset.height();
304 } else {
305 buffer.pos[j] = x;
306 }
307 x += SkFloatToScalar(advances[j]);
345 } 308 }
346 } 309 }
347 310 return true;
348 return adoptRef(builder.build());
349 } 311 }
350 312
313 } // namespace
314
315 PassTextBlobPtr Font::buildTextBlob(const GlyphBuffer& glyphBuffer, float initia lAdvance, const FloatRect& bounds) const
316 {
317 ASSERT(RuntimeEnabledFeatures::textBlobEnabled());
318
319 SkTextBlobBuilder builder;
320 SkScalar advance = SkFloatToScalar(initialAdvance);
321
322 bool success = glyphBuffer.hasOffsets() ?
323 buildTextBlobInternal<true>(glyphBuffer, advance, builder) :
324 buildTextBlobInternal<false>(glyphBuffer, advance, builder);
325 return success ? adoptRef(builder.build()) : nullptr;
326 }
327
328
351 } // namespace blink 329 } // namespace blink
OLDNEW
« no previous file with comments | « sky/engine/platform/fonts/GlyphBufferTest.cpp ('k') | sky/engine/platform/fonts/harfbuzz/HarfBuzzShaper.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698